Beispiel #1
0
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
    Volume3DOverlay::removeFromScene(overlay, scene, transaction);
    _model->removeFromScene(scene, transaction);
    emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getID(), NestableType::Overlay, _model);
    transaction.updateItem<Overlay>(getRenderItemID(), [](Overlay& data) {
        auto modelOverlay = static_cast<ModelOverlay*>(&data);
        modelOverlay->clearSubRenderItemIDs();
    });
}
Beispiel #2
0
void Text3DOverlay::setProperties(const QVariantMap& properties) {
    Billboard3DOverlay::setProperties(properties);

    auto text = properties["text"];
    if (text.isValid()) {
        setText(text.toString());
    }

    auto textAlpha = properties["textAlpha"];
    if (textAlpha.isValid()) {
        float prevTextAlpha = getTextAlpha();
        setTextAlpha(textAlpha.toFloat());
        // Update our payload key if necessary to handle transparency
        if ((prevTextAlpha < 1.0f && _textAlpha >= 1.0f) || (prevTextAlpha >= 1.0f && _textAlpha < 1.0f)) {
            auto itemID = getRenderItemID();
            if (render::Item::isValidID(itemID)) {
                render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
                render::Transaction transaction;
                transaction.updateItem(itemID);
                scene->enqueueTransaction(transaction);
            }
        }
    }

    bool valid;
    auto backgroundColor = properties["backgroundColor"];
    if (backgroundColor.isValid()) {
        auto color = u8vec3FromVariant(backgroundColor, valid);
        if (valid) {
            _backgroundColor = color;
        }
    }

    if (properties["backgroundAlpha"].isValid()) {
        setAlpha(properties["backgroundAlpha"].toFloat());
    }

    if (properties["lineHeight"].isValid()) {
        setLineHeight(properties["lineHeight"].toFloat());
    }

    if (properties["leftMargin"].isValid()) {
        setLeftMargin(properties["leftMargin"].toFloat());
    }

    if (properties["topMargin"].isValid()) {
        setTopMargin(properties["topMargin"].toFloat());
    }

    if (properties["rightMargin"].isValid()) {
        setRightMargin(properties["rightMargin"].toFloat());
    }

    if (properties["bottomMargin"].isValid()) {
        setBottomMargin(properties["bottomMargin"].toFloat());
    }
}
Beispiel #3
0
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
    auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar);
    AvatarHashMap::handleRemovedAvatar(avatar, removalReason);
    avatar->tearDownGrabs();

    avatar->die();
    queuePhysicsChange(avatar);

    // remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor
    // it might not fire until after we create a new instance for the same remote avatar, which creates a race
    // on the creation of entities for that avatar instance and the deletion of entities for this instance
    avatar->removeAvatarEntitiesFromTree();
    if (removalReason != KillAvatarReason::AvatarDisconnected) {
        if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) {
            emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID());
            emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius();
        }

        workload::Transaction workloadTransaction;
        workloadTransaction.remove(avatar->getSpaceIndex());
        _space->enqueueTransaction(workloadTransaction);

        const render::ScenePointer& scene = qApp->getMain3DScene();
        render::Transaction transaction;
        avatar->removeFromScene(avatar, scene, transaction);
        scene->enqueueTransaction(transaction);
    } else {
        // remove from node sets, if present
        DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
        DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
        render::Transaction transaction;
        auto scene = qApp->getMain3DScene();
        avatar->fadeOut(transaction, removalReason);

        workload::SpacePointer space = _space;
        transaction.transitionFinishedOperator(avatar->getRenderItemID(), [space, avatar]() {
            if (avatar->getLastFadeRequested() != render::Transition::Type::USER_LEAVE_DOMAIN) {
                // The avatar is using another transition besides the fade-out transition, which means it is still in use.
                // Deleting the avatar now could cause state issues, so abort deletion and show message.
                qCWarning(interfaceapp) << "An ending fade-out transition wants to delete an avatar, but the avatar is still in use. Avatar deletion has aborted. (avatar ID: " << avatar->getSessionUUID() << ")";
            } else {
                const render::ScenePointer& scene = qApp->getMain3DScene();
                render::Transaction transaction;
                avatar->removeFromScene(avatar, scene, transaction);
                scene->enqueueTransaction(transaction);

                workload::Transaction workloadTransaction;
                workloadTransaction.remove(avatar->getSpaceIndex());
                space->enqueueTransaction(workloadTransaction);
            }
        });
        scene->enqueueTransaction(transaction);
    }
}
Beispiel #4
0
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
    auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar);
    AvatarHashMap::handleRemovedAvatar(avatar, removalReason);
    avatar->tearDownGrabs();

    avatar->die();
    queuePhysicsChange(avatar);

    // remove this avatar's entities from the tree now, if we wait (as we did previously) for this Avatar's destructor
    // it might not fire until after we create a new instance for the same remote avatar, which creates a race
    // on the creation of entities for that avatar instance and the deletion of entities for this instance
    avatar->removeAvatarEntitiesFromTree();
    if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) {
        emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID());
        emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius();

        workload::Transaction workloadTransaction;
        workloadTransaction.remove(avatar->getSpaceIndex());
        _space->enqueueTransaction(workloadTransaction);

        const render::ScenePointer& scene = qApp->getMain3DScene();
        render::Transaction transaction;
        avatar->removeFromScene(avatar, scene, transaction);
        scene->enqueueTransaction(transaction);
    } else if (removalReason == KillAvatarReason::AvatarDisconnected) {
        // remove from node sets, if present
        DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
        DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
        render::Transaction transaction;
        auto scene = qApp->getMain3DScene();
        avatar->fadeOut(transaction, removalReason);

        workload::SpacePointer space = _space;
        transaction.transitionFinishedOperator(avatar->getRenderItemID(), [space, avatar]() {
            const render::ScenePointer& scene = qApp->getMain3DScene();
            render::Transaction transaction;
            avatar->removeFromScene(avatar, scene, transaction);
            scene->enqueueTransaction(transaction);

            workload::Transaction workloadTransaction;
            workloadTransaction.remove(avatar->getSpaceIndex());
            space->enqueueTransaction(workloadTransaction);
        });
        scene->enqueueTransaction(transaction);
    }
}
Beispiel #5
0
void ModelOverlay::update(float deltatime) {
    if (_updateModel) {
        _updateModel = false;
        _model->setSnapModelToCenter(true);
        Transform transform = evalRenderTransform();
        if (_scaleToFit) {
            _model->setScaleToFit(true, transform.getScale() * getDimensions());
        } else {
            _model->setScale(transform.getScale());
        }
        _model->setRotation(transform.getRotation());
        _model->setTranslation(transform.getTranslation());
        _model->setURL(_url);
        _model->simulate(deltatime, true);
    } else {
        _model->simulate(deltatime);
    }
    _isLoaded = _model->isActive();

    if (isAnimatingSomething()) {
        if (!jointsMapped()) {
            mapAnimationJoints(_model->getJointNames());
        }
        animate();
    }

    // check to see if when we added our model to the scene they were ready, if they were not ready, then
    // fix them up in the scene
    render::ScenePointer scene = qApp->getMain3DScene();
    render::Transaction transaction;
    if (_model->needsFixupInScene()) {
        emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getID(), NestableType::Overlay, _model);
        _model->removeFromScene(scene, transaction);
        _model->addToScene(scene, transaction);

        auto newRenderItemIDs{ _model->fetchRenderItemIDs() };
        transaction.updateItem<Overlay>(getRenderItemID(), [newRenderItemIDs](Overlay& data) {
            auto modelOverlay = static_cast<ModelOverlay*>(&data);
            modelOverlay->setSubRenderItemIDs(newRenderItemIDs);
        });
        processMaterials();
        emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getID(), NestableType::Overlay, _model);
    }
    if (_visibleDirty) {
        _visibleDirty = false;
        // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true
        _model->setVisibleInScene(getVisible(), scene,
                                  render::ItemKey::TAG_BITS_0 |
                                  (_isVisibleInSecondaryCamera ? render::ItemKey::TAG_BITS_1 : render::ItemKey::TAG_BITS_NONE),
                                  false);
    }
    if (_drawInFrontDirty) {
        _drawInFrontDirty = false;
        _model->setLayeredInFront(getDrawInFront(), scene);
    }
    if (_drawInHUDDirty) {
        _drawInHUDDirty = false;
        _model->setLayeredInHUD(getDrawHUDLayer(), scene);
    }
    scene->enqueueTransaction(transaction);

    if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) {
        _texturesLoaded = true;
        _model->updateRenderItems();
    }
}
Beispiel #6
0
void Image3DOverlay::render(RenderArgs* args) {
    if (!_renderVisible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
        return;
    }

    // Once the texture has loaded, check if we need to update the render item because of transparency
    if (!_textureIsLoaded && _texture && _texture->getGPUTexture()) {
        _textureIsLoaded = true;
        bool prevAlphaTexture = _alphaTexture;
        _alphaTexture = _texture->getGPUTexture()->getUsage().isAlpha();
        if (_alphaTexture != prevAlphaTexture) {
            auto itemID = getRenderItemID();
            if (render::Item::isValidID(itemID)) {
                render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
                render::Transaction transaction;
                transaction.updateItem(itemID);
                scene->enqueueTransaction(transaction);
            }
        }
    }

    Q_ASSERT(args->_batch);
    gpu::Batch* batch = args->_batch;

    float imageWidth = _texture->getWidth();
    float imageHeight = _texture->getHeight();

    QRect fromImage;
    if (_fromImage.isNull()) {
        fromImage.setX(0);
        fromImage.setY(0);
        fromImage.setWidth(imageWidth);
        fromImage.setHeight(imageHeight);
    } else {
        float scaleX = imageWidth / _texture->getOriginalWidth();
        float scaleY = imageHeight / _texture->getOriginalHeight();

        fromImage.setX(scaleX * _fromImage.x());
        fromImage.setY(scaleY * _fromImage.y());
        fromImage.setWidth(scaleX * _fromImage.width());
        fromImage.setHeight(scaleY * _fromImage.height());
    }

    float maxSize = glm::max(fromImage.width(), fromImage.height());
    float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f;
    float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f;

    glm::vec2 topLeft(-x, -y);
    glm::vec2 bottomRight(x, y);
    glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight);
    glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
                                  (fromImage.y() + fromImage.height() - 0.5f) / imageHeight);

    float alpha = getAlpha();
    glm::u8vec3 color = getColor();
    glm::vec4 imageColor(toGlm(color), alpha);

    batch->setModelTransform(getRenderTransform());
    batch->setResourceTexture(0, _texture->getGPUTexture());

    DependencyManager::get<GeometryCache>()->renderQuad(
        *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
        imageColor, _geometryId
    );

    batch->setResourceTexture(0, nullptr); // restore default white color after me
}
Beispiel #7
0
void Base3DOverlay::setProperties(const QVariantMap& properties) {
    Overlay::setProperties(properties);

    bool needRenderItemUpdate = false;

    auto drawInFront = properties["drawInFront"];

    if (drawInFront.isValid()) {
        bool value = drawInFront.toBool();
        setDrawInFront(value);
        needRenderItemUpdate = true;
    }

    auto position = properties["position"];

    // if "position" property was not there, check to see if they included aliases: point, p1
    if (!position.isValid()) {
        position = properties["p1"];
        if (!position.isValid()) {
            position = properties["point"];
        }
    }
    if (position.isValid()) {
        setPosition(vec3FromVariant(position));
        needRenderItemUpdate = true;
    }

    if (properties["lineWidth"].isValid()) {
        setLineWidth(properties["lineWidth"].toFloat());
        needRenderItemUpdate = true;
    }

    auto rotation = properties["rotation"];

    if (rotation.isValid()) {
        setRotation(quatFromVariant(rotation));
        needRenderItemUpdate = true;
    }

    if (properties["isSolid"].isValid()) {
        setIsSolid(properties["isSolid"].toBool());
    }
    if (properties["isFilled"].isValid()) {
        setIsSolid(properties["isSolid"].toBool());
    }
    if (properties["isWire"].isValid()) {
        setIsSolid(!properties["isWire"].toBool());
    }
    if (properties["solid"].isValid()) {
        setIsSolid(properties["solid"].toBool());
    }
    if (properties["filled"].isValid()) {
        setIsSolid(properties["filled"].toBool());
    }
    if (properties["wire"].isValid()) {
        setIsSolid(!properties["wire"].toBool());
    }

    if (properties["isDashedLine"].isValid()) {
        setIsDashedLine(properties["isDashedLine"].toBool());
    }
    if (properties["dashed"].isValid()) {
        setIsDashedLine(properties["dashed"].toBool());
    }
    if (properties["ignoreRayIntersection"].isValid()) {
        setIgnoreRayIntersection(properties["ignoreRayIntersection"].toBool());
    }

    // Communicate changes to the renderItem if needed
    if (needRenderItemUpdate) {
        auto itemID = getRenderItemID();
        if (render::Item::isValidID(itemID)) {
            render::ScenePointer scene = qApp->getMain3DScene();
            render::PendingChanges pendingChanges;
            pendingChanges.updateItem(itemID);
            scene->enqueuePendingChanges(pendingChanges);
        }
    }
}