This commit is contained in:
amer cerkic 2019-02-28 10:18:04 -08:00
commit 36cd26b190
23 changed files with 362 additions and 355 deletions

View file

@ -2548,7 +2548,7 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite
_pendingFileContent.seek(_pendingFileContent.size());
_pendingFileContent.write(dataChunk);
_pendingFileContent.close();
// Respond immediately - will timeout if we wait for restore.
connection->respond(HTTPConnection::StatusCode200);
if (itemName == "restore-file" || itemName == "restore-file-chunk-final" || itemName == "restore-file-chunk-only") {

View file

@ -4979,6 +4979,15 @@ void Application::idle() {
}
}
{
if (_keyboardFocusWaitingOnRenderable && getEntities()->renderableForEntityId(_keyboardFocusedEntity.get())) {
_keyboardFocusWaitingOnRenderable = false;
QUuid entityId = _keyboardFocusedEntity.get();
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
setKeyboardFocusEntity(entityId);
}
}
{
PerformanceTimer perfTimer("pluginIdle");
PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()");
@ -5807,7 +5816,7 @@ void Application::setKeyboardFocusEntity(const QUuid& id) {
if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) {
if (id == _loginDialogID) {
emit loginDialogFocusEnabled();
} else {
} else if (!_keyboardFocusWaitingOnRenderable) {
// that's the only entity we want in focus;
return;
}
@ -5824,7 +5833,10 @@ void Application::setKeyboardFocusEntity(const QUuid& id) {
if (properties.getVisible()) {
auto entities = getEntities();
auto entityId = _keyboardFocusedEntity.get();
if (entities->wantsKeyboardFocus(entityId)) {
auto entityItemRenderable = entities->renderableForEntityId(entityId);
if (!entityItemRenderable) {
_keyboardFocusWaitingOnRenderable = true;
} else if (entityItemRenderable->wantsKeyboardFocus()) {
entities->setProxyWindow(entityId, _window->windowHandle());
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->pluginFocusOutEvent();

View file

@ -732,6 +732,7 @@ private:
bool _failedToConnectToEntityServer { false };
bool _reticleClickPressed { false };
bool _keyboardFocusWaitingOnRenderable { false };
int _avatarAttachmentRequest = 0;

View file

@ -32,6 +32,17 @@ void GrabManager::simulateGrabs() {
bool success;
SpatiallyNestablePointer grabbedThing = SpatiallyNestable::findByID(grabbedThingID, success);
if (success && grabbedThing) {
auto entity = std::dynamic_pointer_cast<EntityItem>(grabbedThing);
if (entity) {
if (entity->getLocked()) {
continue; // even if someone else claims to be grabbing it, don't move a locked thing
}
const GrabPropertyGroup& grabProps = entity->getGrabProperties();
if (!grabProps.getGrabbable()) {
continue; // even if someone else claims to be grabbing it, don't move non-grabbable
}
}
glm::vec3 finalPosition = acc.finalizePosition();
glm::quat finalOrientation = acc.finalizeOrientation();
grabbedThing->setTransform(createMatFromQuatAndPos(finalOrientation, finalPosition));

View file

@ -932,7 +932,8 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
bool isPhysicsEnabled = qApp->isPhysicsEnabled();
bool zoneAllowsFlying = zoneInteractionProperties.first;
bool collisionlessAllowed = zoneInteractionProperties.second;
_characterController.setFlyingAllowed((zoneAllowsFlying && _enableFlying) || !isPhysicsEnabled);
_characterController.setZoneFlyingAllowed(zoneAllowsFlying || !isPhysicsEnabled);
_characterController.setComfortFlyingAllowed(_enableFlying);
_characterController.setCollisionlessAllowed(collisionlessAllowed);
}

View file

@ -72,7 +72,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
Locker lock(_lock);
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
if (entity && entity->getCreated() < _startTime) {
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
_trackedEntities.emplace(entityID, entity);
int trackedEntityCount = (int)_trackedEntities.size();
@ -81,7 +81,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
_maxTrackedEntityCount = trackedEntityCount;
_trackedEntityStabilityCount = 0;
}
qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
//qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
}
}
}

View file

@ -295,14 +295,14 @@ QString Overlays::overlayToEntityType(const QString& type) {
} \
}
static QHash<QUuid, glm::quat> savedRotations = QHash<QUuid, glm::quat>();
static QHash<QUuid, std::pair<glm::quat, bool>> savedRotations = QHash<QUuid, std::pair<glm::quat, bool>>();
EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) {
glm::quat rotation;
std::pair<glm::quat, bool> rotation;
return convertOverlayToEntityProperties(overlayProps, rotation, type, add, id);
}
EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id) {
EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id) {
overlayProps["type"] = type;
SET_OVERLAY_PROP_DEFAULT(alpha, 0.7);
@ -563,65 +563,33 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
SET_OVERLAY_PROP_DEFAULT(textures, PathUtils::resourcesUrl() + "images/whitePixel.png");
}
{ // Overlays did this conversion for rotation
auto iter = overlayProps.find("rotation");
if (iter != overlayProps.end() && !overlayProps.contains("localRotation")) {
QUuid parentID;
{
auto iter = overlayProps.find("parentID");
if (iter != overlayProps.end()) {
parentID = iter.value().toUuid();
} else if (!add) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_PARENT_ID;
parentID = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getParentID();
}
}
int parentJointIndex = -1;
{
auto iter = overlayProps.find("parentJointIndex");
if (iter != overlayProps.end()) {
parentJointIndex = iter.value().toInt();
} else if (!add) {
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_PARENT_JOINT_INDEX;
parentJointIndex = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getParentJointIndex();
}
}
glm::quat rotation = quatFromVariant(iter.value());
bool success = false;
glm::quat localRotation = SpatiallyNestable::worldToLocal(rotation, parentID, parentJointIndex, false, success);
if (success) {
overlayProps["rotation"] = quatToVariant(localRotation);
}
}
}
if (type == "Text" || type == "Image" || type == "Grid" || type == "Web") {
glm::quat originalRotation = ENTITY_ITEM_DEFAULT_ROTATION;
bool local = false;
{
auto iter = overlayProps.find("rotation");
if (iter != overlayProps.end()) {
originalRotation = quatFromVariant(iter.value());
local = false;
} else {
iter = overlayProps.find("localRotation");
if (iter != overlayProps.end()) {
originalRotation = quatFromVariant(iter.value());
local = true;
} else if (!add) {
auto iter2 = savedRotations.find(id);
if (iter2 != savedRotations.end()) {
originalRotation = iter2.value();
originalRotation = iter2.value().first;
local = iter2.value().second;
}
}
}
}
if (!add) {
savedRotations[id] = originalRotation;
savedRotations[id] = { originalRotation, local };
} else {
rotationToSave = originalRotation;
rotationToSave = { originalRotation, local };
}
glm::vec3 dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS;
@ -652,7 +620,11 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
rotation = glm::angleAxis((float)M_PI, rotation * Vectors::UP) * rotation;
}
overlayProps["localRotation"] = quatToVariant(rotation);
if (local) {
overlayProps["localRotation"] = quatToVariant(rotation);
} else {
overlayProps["rotation"] = quatToVariant(rotation);
}
overlayProps["dimensions"] = vec3toVariant(glm::abs(dimensions));
}
}
@ -834,7 +806,7 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
if (type == "rectangle3d") {
propertyMap["shape"] = "Quad";
}
glm::quat rotationToSave;
std::pair<glm::quat, bool> rotationToSave;
QUuid id = DependencyManager::get<EntityScriptingInterface>()->addEntityInternal(convertOverlayToEntityProperties(propertyMap, rotationToSave, entityType, true), entity::HostType::LOCAL);
if (entityType == "Text" || entityType == "Image" || entityType == "Grid" || entityType == "Web") {
savedRotations[id] = rotationToSave;

View file

@ -729,7 +729,7 @@ private:
QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps);
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id);
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair<glm::quat, bool>& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid());
private slots:
void mousePressPointerEvent(const QUuid& id, const PointerEvent& event);

View file

@ -99,65 +99,64 @@ void AnimClip::copyFromNetworkAnim() {
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
_anim.clear();
// build a mapping from animation joint indices to skeleton joint indices.
auto avatarSkeleton = getSkeleton();
// build a mapping from animation joint indices to avatar joint indices.
// by matching joints with the same name.
const HFMModel& hfmModel = _networkAnim->getHFMModel();
AnimSkeleton animSkeleton(hfmModel);
const auto animJointCount = animSkeleton.getNumJoints();
const auto skeletonJointCount = _skeleton->getNumJoints();
std::vector<int> jointMap;
jointMap.reserve(animJointCount);
for (int i = 0; i < animJointCount; i++) {
int skeletonJoint = _skeleton->nameToJointIndex(animSkeleton.getJointName(i));
jointMap.push_back(skeletonJoint);
const HFMModel& animModel = _networkAnim->getHFMModel();
AnimSkeleton animSkeleton(animModel);
const int animJointCount = animSkeleton.getNumJoints();
const int avatarJointCount = avatarSkeleton->getNumJoints();
std::vector<int> animToAvatarJointIndexMap;
animToAvatarJointIndexMap.reserve(animJointCount);
for (int animJointIndex = 0; animJointIndex < animJointCount; animJointIndex++) {
QString animJointName = animSkeleton.getJointName(animJointIndex);
int avatarJointIndex = avatarSkeleton->nameToJointIndex(animJointName);
animToAvatarJointIndexMap.push_back(avatarJointIndex);
}
const int frameCount = hfmModel.animationFrames.size();
_anim.resize(frameCount);
const int animFrameCount = animModel.animationFrames.size();
_anim.resize(animFrameCount);
for (int frame = 0; frame < frameCount; frame++) {
for (int frame = 0; frame < animFrameCount; frame++) {
const HFMAnimationFrame& hfmAnimFrame = hfmModel.animationFrames[frame];
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
// init all joints in animation to default pose
// this will give us a resonable result for bones in the model skeleton but not in the animation.
_anim[frame].reserve(skeletonJointCount);
for (int skeletonJoint = 0; skeletonJoint < skeletonJointCount; skeletonJoint++) {
_anim[frame].push_back(_skeleton->getRelativeDefaultPose(skeletonJoint));
// this will give us a resonable result for bones in the avatar skeleton but not in the animation.
_anim[frame].reserve(avatarJointCount);
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
_anim[frame].push_back(avatarSkeleton->getRelativeDefaultPose(avatarJointIndex));
}
for (int animJoint = 0; animJoint < animJointCount; animJoint++) {
int skeletonJoint = jointMap[animJoint];
for (int animJointIndex = 0; animJointIndex < animJointCount; animJointIndex++) {
int avatarJointIndex = animToAvatarJointIndexMap[animJointIndex];
const glm::vec3& hfmAnimTrans = hfmAnimFrame.translations[animJoint];
const glm::quat& hfmAnimRot = hfmAnimFrame.rotations[animJoint];
// skip joints that are in the animation but not in the avatar.
if (avatarJointIndex >= 0 && avatarJointIndex < avatarJointCount) {
// skip joints that are in the animation but not in the skeleton.
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
const glm::quat& animRot = animFrame.rotations[animJointIndex];
AnimPose preRot, postRot;
preRot = animSkeleton.getPreRotationPose(animJoint);
postRot = animSkeleton.getPostRotationPose(animJoint);
const AnimPose& animPreRotPose = animSkeleton.getPreRotationPose(animJointIndex);
AnimPose animPostRotPose = animSkeleton.getPostRotationPose(animJointIndex);
AnimPose animRotPose(glm::vec3(1.0f), animRot, glm::vec3());
// cancel out scale
preRot.scale() = glm::vec3(1.0f);
postRot.scale() = glm::vec3(1.0f);
// adjust anim scale to equal the scale from the avatar joint.
// we do not support animated scale.
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
animPostRotPose.scale() = avatarDefaultPose.scale();
AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3());
// adjust translation offsets, so large translation animatons on the reference skeleton
// will be adjusted when played on a skeleton with short limbs.
const glm::vec3& hfmZeroTrans = hfmModel.animationFrames[0].translations[animJoint];
const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint);
// retarget translation from animation to avatar
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
float boneLengthScale = 1.0f;
const float EPSILON = 0.0001f;
if (fabsf(glm::length(hfmZeroTrans)) > EPSILON) {
boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans);
if (fabsf(glm::length(animZeroTrans)) > EPSILON) {
boneLengthScale = glm::length(avatarDefaultPose.trans()) / glm::length(animZeroTrans);
}
AnimPose animTransPose = AnimPose(glm::vec3(1.0f), glm::quat(), avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans));
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans));
_anim[frame][skeletonJoint] = trans * preRot * rot * postRot;
_anim[frame][avatarJointIndex] = animTransPose * animPreRotPose * animRotPose * animPostRotPose;
}
}
}
@ -165,7 +164,7 @@ void AnimClip::copyFromNetworkAnim() {
// mirrorAnim will be re-built on demand, if needed.
_mirrorAnim.clear();
_poses.resize(skeletonJointCount);
_poses.resize(avatarJointCount);
}
void AnimClip::buildMirrorAnim() {

View file

@ -1066,13 +1066,6 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
if (_enableInverseKinematics) {
_animVars.set("ikOverlayAlpha", 1.0f);
_animVars.set("splineIKEnabled", true);
_animVars.set("leftHandIKEnabled", true);
_animVars.set("rightHandIKEnabled", true);
_animVars.set("leftFootIKEnabled", true);
_animVars.set("rightFootIKEnabled", true);
_animVars.set("leftFootPoleVectorEnabled", true);
_animVars.set("rightFootPoleVectorEnabled", true);
} else {
_animVars.set("ikOverlayAlpha", 0.0f);
_animVars.set("splineIKEnabled", false);
@ -1885,13 +1878,15 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
};
std::shared_ptr<AnimInverseKinematics> ikNode = getAnimInverseKinematicsNode();
for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) {
int index = indexOfJoint(secondaryControllerJointNames[i]);
if ((index >= 0) && (ikNode)) {
if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) {
ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]);
} else {
ikNode->clearSecondaryTarget(index);
if (ikNode) {
for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) {
int index = indexOfJoint(secondaryControllerJointNames[i]);
if (index >= 0) {
if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) {
ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]);
} else {
ikNode->clearSecondaryTarget(index);
}
}
}
}
@ -2184,4 +2179,4 @@ void Rig::initFlow(bool isActive) {
_internalFlow.cleanUp();
_networkFlow.cleanUp();
}
}
}

View file

@ -53,7 +53,7 @@ bool ShapeEntityRenderer::needsRenderUpdate() const {
}
auto mat = _materials.find("0");
if (mat != _materials.end() && (mat->second.needsUpdate() || mat->second.areTexturesLoading())) {
if (mat != _materials.end() && mat->second.shouldUpdate()) {
return true;
}
@ -188,7 +188,7 @@ bool ShapeEntityRenderer::useMaterialPipeline(const graphics::MultiMaterial& mat
ShapeKey ShapeEntityRenderer::getShapeKey() {
auto mat = _materials.find("0");
if (mat != _materials.end() && (mat->second.needsUpdate() || mat->second.areTexturesLoading())) {
if (mat != _materials.end() && mat->second.shouldUpdate()) {
RenderPipelines::updateMultiMaterial(mat->second);
}

View file

@ -101,21 +101,15 @@ bool WebEntityRenderer::isTransparent() const {
}
bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
if (_contextPosition != entity->getWorldPosition()) {
return true;
}
{
QSharedPointer<OffscreenQmlSurface> webSurface;
withReadLock([&] {
webSurface = _webSurface;
});
if (webSurface && uvec2(getWindowSize(entity)) != toGlm(webSurface->size())) {
if (resultWithReadLock<bool>([&] {
if (_webSurface && uvec2(getWindowSize(entity)) != toGlm(_webSurface->size())) {
return true;
}
if (_contextPosition != entity->getWorldPosition()) {
return true;
}
}
if(resultWithReadLock<bool>([&] {
if (_color != entity->getColor()) {
return true;
}
@ -194,7 +188,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
auto newContentType = getContentType(newSourceURL);
ContentType currentContentType;
withReadLock([&] {
urlChanged = _sourceURL != newSourceURL;
urlChanged = newSourceURL.isEmpty() || newSourceURL != _tryingToBuildURL;
});
currentContentType = _contentType;
@ -206,7 +200,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
}
}
withWriteLock([&] {
_inputMode = entity->getInputMode();
_dpi = entity->getDPI();
@ -216,6 +209,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
_billboardMode = entity->getBillboardMode();
if (_contentType == ContentType::NoContent) {
_tryingToBuildURL = newSourceURL;
_sourceURL = newSourceURL;
return;
}
@ -226,10 +221,12 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
if (_webSurface) {
if (_webSurface->getRootItem()) {
if (_contentType == ContentType::HtmlContent && urlChanged) {
if (_contentType == ContentType::HtmlContent && _sourceURL != newSourceURL) {
_webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL);
_sourceURL = newSourceURL;
} else if (_contentType != ContentType::HtmlContent) {
_sourceURL = newSourceURL;
}
_sourceURL = newSourceURL;
{
auto scriptURL = entity->getScriptURL();
@ -294,20 +291,21 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
});
// Try to update the texture
{
QSharedPointer<OffscreenQmlSurface> webSurface;
withReadLock([&] {
webSurface = _webSurface;
});
if (!webSurface) {
return;
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
bool newTextureAvailable = false;
if (!resultWithReadLock<bool>([&] {
if (!_webSurface) {
return false;
}
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
bool newTextureAvailable = webSurface->fetchTexture(newTextureAndFence);
if (newTextureAvailable) {
_texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second);
}
newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence);
return true;
})) {
return;
}
if (newTextureAvailable) {
_texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second);
}
static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f);
@ -351,6 +349,8 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q
_connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) {
emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message);
}));
_tryingToBuildURL = newSourceURL;
}
void WebEntityRenderer::destroyWebSurface() {
@ -383,11 +383,16 @@ glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) con
void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) {
if (_inputMode == WebInputMode::MOUSE) {
handlePointerEvent(event);
} else if (_webSurface) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->hoverBeginEvent(webEvent, _touchDevice);
return;
}
withReadLock([&] {
if (_webSurface) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->hoverBeginEvent(webEvent, _touchDevice);
}
});
}
void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
@ -398,34 +403,39 @@ void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
// QML onReleased is only triggered if a click has happened first. We need to send this "fake" mouse move event to properly trigger an onExited.
PointerEvent endMoveEvent(PointerEvent::Move, event.getID());
handlePointerEvent(endMoveEvent);
} else if (_webSurface) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->hoverEndEvent(webEvent, _touchDevice);
}
}
void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) {
if (_inputMode == WebInputMode::TOUCH) {
handlePointerEventAsTouch(event);
} else {
handlePointerEventAsMouse(event);
}
}
void WebEntityRenderer::handlePointerEventAsTouch(const PointerEvent& event) {
if (_webSurface) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->handlePointerEvent(webEvent, _touchDevice);
}
}
void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) {
if (!_webSurface) {
return;
}
withReadLock([&] {
if (_webSurface) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->hoverEndEvent(webEvent, _touchDevice);
}
});
}
void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) {
withReadLock([&] {
if (!_webSurface) {
return;
}
if (_inputMode == WebInputMode::TOUCH) {
handlePointerEventAsTouch(event);
} else {
handlePointerEventAsMouse(event);
}
});
}
void WebEntityRenderer::handlePointerEventAsTouch(const PointerEvent& event) {
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->handlePointerEvent(webEvent, _touchDevice);
}
void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) {
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi);
QPointF windowPoint(windowPos.x, windowPos.y);
@ -459,16 +469,20 @@ void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) {
}
void WebEntityRenderer::setProxyWindow(QWindow* proxyWindow) {
if (_webSurface) {
_webSurface->setProxyWindow(proxyWindow);
}
withReadLock([&] {
if (_webSurface) {
_webSurface->setProxyWindow(proxyWindow);
}
});
}
QObject* WebEntityRenderer::getEventHandler() {
if (!_webSurface) {
return nullptr;
}
return _webSurface->getEventHandler();
return resultWithReadLock<QObject*>([&]() -> QObject* {
if (!_webSurface) {
return nullptr;
}
return _webSurface->getEventHandler();
});
}
void WebEntityRenderer::emitScriptEvent(const QVariant& message) {

View file

@ -82,6 +82,7 @@ private:
QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr };
bool _cachedWebSurface { false };
gpu::TexturePointer _texture;
QString _tryingToBuildURL;
glm::u8vec3 _color;
float _alpha { 1.0f };

View file

@ -55,13 +55,11 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const
qCDebug(entities) << " oldContainingElement->bestFitBounds(newCubeClamped):"
<< oldContainingElement->bestFitBounds(newCubeClamped);
} else {
qCDebug(entities) << " WARNING NO OLD CONTAINING ELEMENT!!!";
qCDebug(entities) << " WARNING NO OLD CONTAINING ELEMENT for entity" << entity->getEntityItemID();
}
}
if (!oldContainingElement) {
qCDebug(entities) << "UNEXPECTED!!!! attempting to move entity "<< entity->getEntityItemID()
<< "that has no containing element. ";
return; // bail without adding.
}

View file

@ -456,11 +456,11 @@ public:
graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get<graphics::MultiMaterial::Schema>()._key); }
const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; }
bool needsUpdate() const { return _needsUpdate; }
void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; }
void setTexturesLoading(bool value) { _texturesLoading = value; }
bool areTexturesLoading() const { return _texturesLoading; }
void setInitialized() { _initialized = true; }
bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading; }
int getTextureCount() const { calculateMaterialInfo(); return _textureCount; }
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
@ -471,6 +471,7 @@ private:
gpu::TextureTablePointer _textureTable { std::make_shared<gpu::TextureTable>() };
bool _needsUpdate { false };
bool _texturesLoading { false };
bool _initialized { false };
mutable size_t _textureSize { 0 };
mutable int _textureCount { 0 };

View file

@ -315,7 +315,9 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
// wasn't an address - lookup the place name
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path(), trigger);
if (!lookupUrl.host().isNull() && !lookupUrl.host().isEmpty()) {
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path(), trigger);
}
}
}
@ -337,7 +339,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
// be loaded over http(s)
// lookupUrl.scheme() == URL_SCHEME_HTTP ||
// lookupUrl.scheme() == HIFI_URL_SCHEME_HTTPS ||
// TODO once a file can return a connection refusal if there were to be some kind of load error, we'd
// TODO once a file can return a connection refusal if there were to be some kind of load error, we'd
// need to store the previous domain tried in _lastVisitedURL. For now , do not store it.
_previousAPILookup.clear();

View file

@ -645,103 +645,95 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
Node::LocalID localID, bool isReplicated, bool isUpstream,
const QUuid& connectionSecret, const NodePermissions& permissions) {
QReadLocker readLocker(&_nodeMutex);
NodeHash::const_iterator it = _nodeHash.find(uuid);
{
QReadLocker readLocker(&_nodeMutex);
NodeHash::const_iterator it = _nodeHash.find(uuid);
if (it != _nodeHash.end()) {
SharedNodePointer& matchingNode = it->second;
if (it != _nodeHash.end()) {
SharedNodePointer& matchingNode = it->second;
matchingNode->setPublicSocket(publicSocket);
matchingNode->setLocalSocket(localSocket);
matchingNode->setPermissions(permissions);
matchingNode->setConnectionSecret(connectionSecret);
matchingNode->setIsReplicated(isReplicated);
matchingNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
matchingNode->setLocalID(localID);
matchingNode->setPublicSocket(publicSocket);
matchingNode->setLocalSocket(localSocket);
matchingNode->setPermissions(permissions);
matchingNode->setConnectionSecret(connectionSecret);
matchingNode->setIsReplicated(isReplicated);
matchingNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
matchingNode->setLocalID(localID);
return matchingNode;
} else {
auto it = _connectionIDs.find(uuid);
if (it == _connectionIDs.end()) {
_connectionIDs[uuid] = INITIAL_CONNECTION_ID;
return matchingNode;
}
// we didn't have this node, so add them
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
newNode->setIsReplicated(isReplicated);
newNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
newNode->setConnectionSecret(connectionSecret);
newNode->setPermissions(permissions);
newNode->setLocalID(localID);
// move the newly constructed node to the LNL thread
newNode->moveToThread(thread());
if (nodeType == NodeType::AudioMixer) {
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
}
SharedNodePointer newNodePointer(newNode, &QObject::deleteLater);
// if this is a solo node type, we assume that the DS has replaced its assignment and we should kill the previous node
if (SOLO_NODE_TYPES.count(newNode->getType())) {
// while we still have the read lock, see if there is a previous solo node we'll need to remove
auto previousSoloIt = std::find_if(_nodeHash.cbegin(), _nodeHash.cend(), [newNode](const UUIDNodePair& nodePair){
return nodePair.second->getType() == newNode->getType();
});
if (previousSoloIt != _nodeHash.cend()) {
// we have a previous solo node, switch to a write lock so we can remove it
readLocker.unlock();
QWriteLocker writeLocker(&_nodeMutex);
auto oldSoloNode = previousSoloIt->second;
_localIDMap.unsafe_erase(oldSoloNode->getLocalID());
_nodeHash.unsafe_erase(previousSoloIt);
handleNodeKill(oldSoloNode);
// convert the current lock back to a read lock for insertion of new node
writeLocker.unlock();
readLocker.relock();
}
}
// insert the new node and release our read lock
#if defined(Q_OS_ANDROID) || (defined(__clang__) && defined(Q_OS_LINUX))
_nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer));
_localIDMap.insert(std::pair<Node::LocalID, SharedNodePointer>(localID, newNodePointer));
#else
_nodeHash.emplace(newNode->getUUID(), newNodePointer);
_localIDMap.emplace(localID, newNodePointer);
#endif
readLocker.unlock();
qCDebug(networking) << "Added" << *newNode;
auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambdas to hold a strong ref
emit nodeAdded(newNodePointer);
if (newNodePointer->getActiveSocket()) {
emit nodeActivated(newNodePointer);
} else {
connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [this, weakPtr] {
auto sharedPtr = weakPtr.lock();
if (sharedPtr) {
emit nodeActivated(sharedPtr);
disconnect(sharedPtr.data(), &NetworkPeer::socketActivated, this, 0);
}
});
}
// Signal when a socket changes, so we can start the hole punch over.
connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] {
emit nodeSocketUpdated(weakPtr);
});
return newNodePointer;
}
auto removeOldNode = [&](auto node) {
if (node) {
QWriteLocker writeLocker(&_nodeMutex);
_localIDMap.unsafe_erase(node->getLocalID());
_nodeHash.unsafe_erase(node->getUUID());
handleNodeKill(node);
}
};
// if this is a solo node type, we assume that the DS has replaced its assignment and we should kill the previous node
if (SOLO_NODE_TYPES.count(nodeType)) {
removeOldNode(soloNodeOfType(nodeType));
}
// If there is a new node with the same socket, this is a reconnection, kill the old node
removeOldNode(findNodeWithAddr(publicSocket));
removeOldNode(findNodeWithAddr(localSocket));
auto it = _connectionIDs.find(uuid);
if (it == _connectionIDs.end()) {
_connectionIDs[uuid] = INITIAL_CONNECTION_ID;
}
// we didn't have this node, so add them
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket);
newNode->setIsReplicated(isReplicated);
newNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType));
newNode->setConnectionSecret(connectionSecret);
newNode->setPermissions(permissions);
newNode->setLocalID(localID);
// move the newly constructed node to the LNL thread
newNode->moveToThread(thread());
if (nodeType == NodeType::AudioMixer) {
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
}
SharedNodePointer newNodePointer(newNode, &QObject::deleteLater);
{
QReadLocker readLocker(&_nodeMutex);
// insert the new node and release our read lock
_nodeHash.insert({ newNode->getUUID(), newNodePointer });
_localIDMap.insert({ localID, newNodePointer });
}
qCDebug(networking) << "Added" << *newNode;
auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambdas to hold a strong ref
emit nodeAdded(newNodePointer);
if (newNodePointer->getActiveSocket()) {
emit nodeActivated(newNodePointer);
} else {
connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [this, weakPtr] {
auto sharedPtr = weakPtr.lock();
if (sharedPtr) {
emit nodeActivated(sharedPtr);
disconnect(sharedPtr.data(), &NetworkPeer::socketActivated, this, 0);
}
});
}
// Signal when a socket changes, so we can start the hole punch over.
connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] {
emit nodeSocketUpdated(weakPtr);
});
return newNodePointer;
}
std::unique_ptr<NLPacket> LimitedNodeList::constructPingPacket(const QUuid& nodeId, PingType_t pingType) {

View file

@ -781,18 +781,18 @@ void CharacterController::updateState() {
const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight);
if ((velocity.dot(_currentUp) <= (jumpSpeed / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) {
SET_STATE(State::Ground, "hit ground");
} else if (_flyingAllowed) {
} else if (_zoneFlyingAllowed) {
btVector3 desiredVelocity = _targetVelocity;
if (desiredVelocity.length2() < MIN_TARGET_SPEED_SQUARED) {
desiredVelocity = btVector3(0.0f, 0.0f, 0.0f);
}
bool vertTargetSpeedIsNonZero = desiredVelocity.dot(_currentUp) > MIN_TARGET_SPEED;
if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
SET_STATE(State::Hover, "double jump button");
} else if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
} else if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
SET_STATE(State::Hover, "jump button held");
} else if (_floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) {
// Transition to hover if we are above the fall threshold
} else if ((!rayHasHit && !_hasSupport) || _floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) {
// Transition to hover if there's no ground beneath us or we are above the fall threshold, regardless of _comfortFlyingAllowed
SET_STATE(State::Hover, "above fall threshold");
}
}
@ -801,8 +801,10 @@ void CharacterController::updateState() {
case State::Hover:
btScalar horizontalSpeed = (velocity - velocity.dot(_currentUp) * _currentUp).length();
bool flyingFast = horizontalSpeed > (MAX_WALKING_SPEED * 0.75f);
if (!_flyingAllowed) {
SET_STATE(State::InAir, "flying not allowed");
if (!_zoneFlyingAllowed) {
SET_STATE(State::InAir, "zone flying not allowed");
} else if (!_comfortFlyingAllowed && (rayHasHit || _hasSupport || _floorDistance < FLY_TO_GROUND_THRESHOLD)) {
SET_STATE(State::InAir, "comfort flying not allowed");
} else if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
SET_STATE(State::InAir, "near ground");
} else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) {
@ -847,12 +849,6 @@ bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPositio
return true;
}
void CharacterController::setFlyingAllowed(bool value) {
if (value != _flyingAllowed) {
_flyingAllowed = value;
}
}
void CharacterController::setCollisionlessAllowed(bool value) {
if (value != _collisionlessAllowed) {
_collisionlessAllowed = value;

View file

@ -65,10 +65,10 @@ public:
// overrides from btCharacterControllerInterface
virtual void setWalkDirection(const btVector3 &walkDirection) override { assert(false); }
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
virtual void reset(btCollisionWorld* collisionWorld) override { }
virtual void warp(const btVector3& origin) override { }
virtual void debugDraw(btIDebugDraw* debugDrawer) override { }
virtual void setUpInterpolate(bool value) override { }
virtual void reset(btCollisionWorld* collisionWorld) override {}
virtual void warp(const btVector3& origin) override {}
virtual void debugDraw(btIDebugDraw* debugDrawer) override {}
virtual void setUpInterpolate(bool value) override {}
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override;
virtual void preStep(btCollisionWorld *collisionWorld) override;
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override;
@ -90,7 +90,7 @@ public:
void preSimulation();
void postSimulation();
void setPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation);
void setPositionAndOrientation(const glm::vec3& position, const glm::quat& orientation);
void getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const;
void setParentVelocity(const glm::vec3& parentVelocity);
@ -129,7 +129,8 @@ public:
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
void setFlyingAllowed(bool value);
void setZoneFlyingAllowed(bool value) { _zoneFlyingAllowed = value; }
void setComfortFlyingAllowed(bool value) { _comfortFlyingAllowed = value; }
void setCollisionlessAllowed(bool value);
void setPendingFlagsUpdateCollisionMask(){ _pendingFlags |= PENDING_FLAG_UPDATE_COLLISION_MASK; }
@ -212,7 +213,8 @@ protected:
uint32_t _pendingFlags { 0 };
uint32_t _previousFlags { 0 };
bool _flyingAllowed { true };
bool _zoneFlyingAllowed { true };
bool _comfortFlyingAllowed { true };
bool _collisionlessAllowed { true };
bool _collisionless { false };

View file

@ -83,7 +83,7 @@ void MeshPartPayload::updateKey(const render::ItemKey& key) {
ItemKey::Builder builder(key);
builder.withTypeShape();
if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) {
if (_drawMaterials.shouldUpdate()) {
RenderPipelines::updateMultiMaterial(_drawMaterials);
}
@ -329,7 +329,7 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) {
builder.withDeformed();
}
if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) {
if (_drawMaterials.shouldUpdate()) {
RenderPipelines::updateMultiMaterial(_drawMaterials);
}
@ -347,7 +347,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr
return;
}
if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) {
if (_drawMaterials.shouldUpdate()) {
RenderPipelines::updateMultiMaterial(_drawMaterials);
}

View file

@ -382,11 +382,6 @@ void RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Bat
void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) {
auto& schemaBuffer = multiMaterial.getSchemaBuffer();
if (multiMaterial.size() == 0) {
schemaBuffer.edit<graphics::MultiMaterial::Schema>() = graphics::MultiMaterial::Schema();
return;
}
auto& drawMaterialTextures = multiMaterial.getTextureTable();
multiMaterial.setTexturesLoading(false);
@ -732,14 +727,11 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
schema._key = (uint32_t)schemaKey._flags.to_ulong();
schemaBuffer.edit<graphics::MultiMaterial::Schema>() = schema;
multiMaterial.setNeedsUpdate(false);
multiMaterial.setInitialized();
}
void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) {
if (multiMaterial.size() == 0) {
return;
}
if (multiMaterial.needsUpdate() || multiMaterial.areTexturesLoading()) {
if (multiMaterial.shouldUpdate()) {
updateMultiMaterial(multiMaterial);
}

View file

@ -325,6 +325,11 @@
leftMargin: domainNameLeftMargin
};
// check to be sure we are going to look for an actual domain
if (!domain) {
doRequest = false;
}
if (doRequest) {
var url = Account.metaverseServerURL + '/api/v1/places/' + domain;
request({

View file

@ -708,7 +708,7 @@ SelectionDisplay = (function() {
shape: "Cone",
solid: true,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true
};
var handlePropertiesTranslateArrowCylinders = {
@ -716,7 +716,7 @@ SelectionDisplay = (function() {
shape: "Cylinder",
solid: true,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true
};
var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
@ -741,7 +741,7 @@ SelectionDisplay = (function() {
majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE,
majorTickMarksLength: 0.1,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true
};
var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
@ -766,7 +766,7 @@ SelectionDisplay = (function() {
solid: true,
innerRadius: 0.9,
visible: false,
ignoreRayIntersection: true,
ignorePickIntersection: true,
drawInFront: true
});
@ -779,7 +779,7 @@ SelectionDisplay = (function() {
visible: false,
isFacingAvatar: true,
drawInFront: true,
ignoreRayIntersection: true,
ignorePickIntersection: true,
dimensions: { x: 0, y: 0 },
lineHeight: 0.0,
topMargin: 0,
@ -791,7 +791,7 @@ SelectionDisplay = (function() {
var handlePropertiesStretchCubes = {
solid: true,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true
};
var handleStretchXCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
@ -802,18 +802,17 @@ SelectionDisplay = (function() {
Overlays.editOverlay(handleStretchZCube, { color: COLOR_BLUE });
var handlePropertiesStretchPanel = {
shape: "Quad",
alpha: 0.5,
solid: true,
visible: false,
ignoreRayIntersection: true,
ignorePickIntersection: true,
drawInFront: true
};
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
var handleStretchXPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED });
var handleStretchYPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
var handleStretchYPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN });
var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
var handleStretchZPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
var handleScaleCube = Overlays.addOverlay("cube", {
@ -821,7 +820,7 @@ SelectionDisplay = (function() {
color: COLOR_SCALE_CUBE,
solid: true,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true,
borderSize: 1.4
});
@ -841,7 +840,7 @@ SelectionDisplay = (function() {
color: COLOR_GREEN,
solid: true,
visible: false,
ignoreRayIntersection: false,
ignorePickIntersection: true,
drawInFront: true,
borderSize: 1.4
});
@ -854,6 +853,7 @@ SelectionDisplay = (function() {
alpha: 0,
solid: false,
visible: false,
ignorePickIntersection: true,
dashed: false
});
@ -865,6 +865,7 @@ SelectionDisplay = (function() {
alpha: 0,
solid: false,
visible: false,
ignorePickIntersection: true,
dashed: false
});
@ -877,7 +878,7 @@ SelectionDisplay = (function() {
green: 0,
blue: 0
},
ignoreRayIntersection: true // always ignore this
ignorePickIntersection: true // always ignore this
});
var yRailOverlay = Overlays.addOverlay("line3d", {
visible: false,
@ -888,7 +889,7 @@ SelectionDisplay = (function() {
green: 255,
blue: 0
},
ignoreRayIntersection: true // always ignore this
ignorePickIntersection: true // always ignore this
});
var zRailOverlay = Overlays.addOverlay("line3d", {
visible: false,
@ -899,7 +900,7 @@ SelectionDisplay = (function() {
green: 0,
blue: 255
},
ignoreRayIntersection: true // always ignore this
ignorePickIntersection: true // always ignore this
});
var allOverlays = [
@ -972,7 +973,7 @@ SelectionDisplay = (function() {
color: COLOR_DEBUG_PICK_PLANE,
solid: true,
visible: false,
ignoreRayIntersection: true,
ignorePickIntersection: true,
drawInFront: false
});
var debugPickPlaneHits = [];
@ -1802,6 +1803,7 @@ SelectionDisplay = (function() {
isActiveTool(handleRotateYawRing) ||
isActiveTool(handleRotateRollRing);
selectionBoxGeometry.visible = !inModeRotate && !isCameraInsideBox;
selectionBoxGeometry.ignorePickIntersection = !selectionBoxGeometry.visible;
Overlays.editOverlay(selectionBox, selectionBoxGeometry);
// UPDATE ICON TRANSLATE HANDLE
@ -1811,9 +1813,13 @@ SelectionDisplay = (function() {
rotation: rotation
};
iconSelectionBoxGeometry.visible = !inModeRotate && isCameraInsideBox;
iconSelectionBoxGeometry.ignorePickIntersection = !iconSelectionBoxGeometry.visible;
Overlays.editOverlay(iconSelectionBox, iconSelectionBoxGeometry);
} else {
Overlays.editOverlay(iconSelectionBox, { visible: false });
Overlays.editOverlay(iconSelectionBox, {
visible: false,
ignorePickIntersection: true
});
}
// UPDATE DUPLICATOR (CURRENTLY HIDDEN FOR NOW)
@ -1882,7 +1888,7 @@ SelectionDisplay = (function() {
// FUNCTION: SET OVERLAYS VISIBLE
that.setOverlaysVisible = function(isVisible) {
for (var i = 0, length = allOverlays.length; i < length; i++) {
Overlays.editOverlay(allOverlays[i], { visible: isVisible });
Overlays.editOverlay(allOverlays[i], { visible: isVisible, ignorePickIntersection: !isVisible });
}
};
@ -1894,18 +1900,18 @@ SelectionDisplay = (function() {
};
that.setHandleTranslateXVisible = function(isVisible) {
Overlays.editOverlay(handleTranslateXCone, { visible: isVisible });
Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible });
Overlays.editOverlay(handleTranslateXCone, { visible: isVisible, ignorePickIntersection: !isVisible });
Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleTranslateYVisible = function(isVisible) {
Overlays.editOverlay(handleTranslateYCone, { visible: isVisible });
Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible });
Overlays.editOverlay(handleTranslateYCone, { visible: isVisible, ignorePickIntersection: !isVisible });
Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleTranslateZVisible = function(isVisible) {
Overlays.editOverlay(handleTranslateZCone, { visible: isVisible });
Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible });
Overlays.editOverlay(handleTranslateZCone, { visible: isVisible, ignorePickIntersection: !isVisible });
Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
};
// FUNCTION: SET HANDLE ROTATE VISIBLE
@ -1916,15 +1922,15 @@ SelectionDisplay = (function() {
};
that.setHandleRotatePitchVisible = function(isVisible) {
Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible });
Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleRotateYawVisible = function(isVisible) {
Overlays.editOverlay(handleRotateYawRing, { visible: isVisible });
Overlays.editOverlay(handleRotateYawRing, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleRotateRollVisible = function(isVisible) {
Overlays.editOverlay(handleRotateRollRing, { visible: isVisible });
Overlays.editOverlay(handleRotateRollRing, { visible: isVisible, ignorePickIntersection: !isVisible });
};
// FUNCTION: SET HANDLE STRETCH VISIBLE
@ -1935,15 +1941,15 @@ SelectionDisplay = (function() {
};
that.setHandleStretchXVisible = function(isVisible) {
Overlays.editOverlay(handleStretchXCube, { visible: isVisible });
Overlays.editOverlay(handleStretchXCube, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleStretchYVisible = function(isVisible) {
Overlays.editOverlay(handleStretchYCube, { visible: isVisible });
Overlays.editOverlay(handleStretchYCube, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleStretchZVisible = function(isVisible) {
Overlays.editOverlay(handleStretchZCube, { visible: isVisible });
Overlays.editOverlay(handleStretchZCube, { visible: isVisible, ignorePickIntersection: !isVisible });
};
// FUNCTION: SET HANDLE SCALE VISIBLE
@ -1953,16 +1959,16 @@ SelectionDisplay = (function() {
};
that.setHandleScaleVisible = function(isVisible) {
Overlays.editOverlay(handleScaleCube, { visible: isVisible });
Overlays.editOverlay(handleScaleCube, { visible: isVisible, ignorePickIntersection: !isVisible });
};
that.setHandleBoundingBoxVisible = function(isVisible) {
Overlays.editOverlay(handleBoundingBox, { visible: isVisible });
Overlays.editOverlay(handleBoundingBox, { visible: isVisible, ignorePickIntersection: true });
};
// FUNCTION: SET HANDLE DUPLICATOR VISIBLE
that.setHandleDuplicatorVisible = function(isVisible) {
Overlays.editOverlay(handleDuplicator, { visible: isVisible });
Overlays.editOverlay(handleDuplicator, { visible: isVisible, ignorePickIntersection: !isVisible });
};
// FUNCTION: DEBUG PICK PLANE
@ -1975,7 +1981,7 @@ SelectionDisplay = (function() {
position: pickPlanePosition,
rotation: rotation,
dimensions: dimensions,
visible: true
visible: true
});
};
@ -1986,7 +1992,7 @@ SelectionDisplay = (function() {
shape: "Sphere",
solid: true,
visible: true,
ignoreRayIntersection: true,
ignorePickIntersection: true,
drawInFront: false,
color: COLOR_DEBUG_PICK_PLANE_HIT,
position: pickHitPosition,
@ -2082,10 +2088,12 @@ SelectionDisplay = (function() {
pushCommandForSelections(duplicatedEntityIDs);
if (isConstrained) {
Overlays.editOverlay(xRailOverlay, {
visible: false
visible: false,
ignorePickIntersection: true
});
Overlays.editOverlay(zRailOverlay, {
visible: false
visible: false,
ignorePickIntersection: true
});
}
},
@ -2174,22 +2182,26 @@ SelectionDisplay = (function() {
Overlays.editOverlay(xRailOverlay, {
start: xStart,
end: xEnd,
visible: true
visible: true,
ignorePickIntersection: true
});
Overlays.editOverlay(zRailOverlay, {
start: zStart,
end: zEnd,
visible: true
visible: true,
ignorePickIntersection: true
});
isConstrained = true;
}
} else {
if (isConstrained) {
Overlays.editOverlay(xRailOverlay, {
visible: false
visible: false,
ignorePickIntersection: true
});
Overlays.editOverlay(zRailOverlay, {
visible: false
visible: false,
ignorePickIntersection: true
});
isConstrained = false;
}
@ -2460,7 +2472,7 @@ SelectionDisplay = (function() {
}
if (stretchPanel !== null) {
Overlays.editOverlay(stretchPanel, { visible: true });
Overlays.editOverlay(stretchPanel, { visible: true, ignorePickIntersection: false });
}
var stretchCubePosition = Overlays.getProperty(handleStretchCube, "position");
var stretchPanelPosition = Overlays.getProperty(stretchPanel, "position");
@ -2481,7 +2493,7 @@ SelectionDisplay = (function() {
}
if (stretchPanel !== null) {
Overlays.editOverlay(stretchPanel, { visible: false });
Overlays.editOverlay(stretchPanel, { visible: false, ignorePickIntersection: true });
}
activeStretchCubePanelOffset = null;
@ -2775,7 +2787,8 @@ SelectionDisplay = (function() {
rotation: worldRotation,
startAt: 0,
endAt: 0,
visible: true
visible: true,
ignorePickIntersection: false
});
// editOverlays may not have committed rotation changes.
@ -2805,13 +2818,13 @@ SelectionDisplay = (function() {
if (wantDebug) {
print("================== " + getMode() + "(addHandleRotateTool onEnd) -> =======================");
}
Overlays.editOverlay(rotationDegreesDisplay, { visible: false });
Overlays.editOverlay(rotationDegreesDisplay, { visible: false, ignorePickIntersection: true });
Overlays.editOverlay(selectedHandle, {
hasTickMarks: false,
solid: true,
innerRadius: ROTATE_RING_IDLE_INNER_RADIUS
});
Overlays.editOverlay(handleRotateCurrentRing, { visible: false });
Overlays.editOverlay(handleRotateCurrentRing, { visible: false, ignorePickIntersection: true });
pushCommandForSelections();
if (wantDebug) {
print("================== " + getMode() + "(addHandleRotateTool onEnd) <- =======================");