ksuprynowiczFix comiler warningsea07a151 year agoHistory
582 lines · 26.8 KB · C++
RawDownload
////  Created by Sam Gondelman 10/20/2017//  Copyright 2017 High Fidelity, Inc.//  Copyright 2022-2023 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  SPDX-License-Identifier: Apache-2.0// #include "PickScriptingInterface.h" #include <QVariant>#include "GLMHelpers.h" #include "Application.h"#include <PickManager.h> #include "RayPick.h"#include "StylusPick.h"#include "ParabolaPick.h"#include "CollisionPick.h" #include "CameraRootTransformNode.h"#include "SpatialParentFinder.h"#include "PickTransformNode.h"#include "MouseTransformNode.h"#include "avatar/MyAvatarHeadTransformNode.h"#include "avatar/AvatarManager.h"#include "NestableTransformNode.h"#include "avatars-renderer/AvatarTransformNode.h"#include "EntityTransformNode.h" #include <ScriptEngine.h>#include <ScriptEngineCast.h>#include <ScriptEngineLogging.h>#include <ScriptValueUtils.h> STATIC_SCRIPT_TYPES_INITIALIZER(+[](ScriptManager* manager){    auto scriptEngine = manager->engine().get();     PickScriptingInterface::registerMetaTypes(scriptEngine);}); STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager){    auto scriptEngine = manager->engine().get();     auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();    if (pickScriptingInterface) {        pickScriptingInterface->registerProperties(scriptEngine);    } else {        qWarning(scriptengine) << "Cannot register PickScriptingInterface properties with script engine, PickScriptingInterface instance not available";    }}); static const float WEB_TOUCH_Y_OFFSET = 0.105f;  // how far forward (or back with a negative number) to slide stylus in handstatic const glm::vec3 TIP_OFFSET = glm::vec3(0.0f, StylusPick::WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, 0.0f); unsigned int PickScriptingInterface::createPick(const PickQuery::PickType type, const QVariant& properties) {    std::shared_ptr<PickQuery> pick;    QVariantMap propMap = properties.toMap();     switch (type) {        case PickQuery::PickType::Ray:            pick = buildRayPick(propMap);            break;        case PickQuery::PickType::Stylus:            pick = buildStylusPick(propMap);            break;        case PickQuery::PickType::Parabola:            pick = buildParabolaPick(propMap);            break;        case PickQuery::PickType::Collision:            pick = buildCollisionPick(propMap);            break;        default:            break;    }     if (!pick) {        return PickManager::INVALID_PICK_ID;    }     propMap["pickType"] = (int)type;     pick->setScriptParameters(propMap);     return DependencyManager::get<PickManager>()->addPick(type, pick);} PickFilter getPickFilter(unsigned int filter) {    // FIXME: Picks always intersect visible and collidable things right now    filter = filter | (PickScriptingInterface::getPickIncludeVisible() | PickScriptingInterface::getPickIncludeCollidable());    return PickFilter(filter);} /*@jsdoc * The properties of a ray pick. * * @typedef {object} Picks.RayPickProperties * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should  *     start disabled. Disabled picks do not update their pick results. * @property {FilterFlags} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property  *     values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code>  *     means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint.  *     A value of <code>0</code> means no joint. *     <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to  *     the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not  *     parented to anything. *     <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {Vec3} [position=Vec3.ZERO] - The offset of the ray origin from its parent if parented, otherwise the ray origin  *     in world coordinates. * @property {Vec3} [posOffset] - Synonym for <code>position</code>. * @property {Vec3} [direction] - The offset of the ray direction from its parent's y-axis if parented, otherwise the ray *     direction in world coordinates. *     <p><strong>Default Value:</strong> <code>Vec3.UP</code> direction if <code>joint</code> is specified, otherwise *     <code>-Vec3.UP</code>.</p> * @property {Vec3} [dirOffset] - Synonym for <code>direction</code>. * @property {Quat} [orientation] - Alternative property for specifying <code>direction</code>. The value is applied to the  *     default <code>direction</code> value. * @property {number} [delay=0.0] - The delay, in seconds, to apply to the ray direction. * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or  *     {@link Picks.getPickScriptParameters}. A ray pick's type is {@link PickType.Ray}. * @property {Vec3} baseScale - Returned from {@link Picks.getPickProperties} when the pick has a parent with varying scale  *     (usually an avatar or an entity). Its value is the original scale of the parent at the moment the pick was created, and  *     is used to scale the pointer which owns this pick, if any. */std::shared_ptr<PickQuery> PickScriptingInterface::buildRayPick(const QVariantMap& propMap) {#if defined (Q_OS_ANDROID)    QString jointName { "" };    if (propMap["joint"].isValid()) {        QString jointName = propMap["joint"].toString();        const QString MOUSE_JOINT = "Mouse";        if (jointName == MOUSE_JOINT) {            return nullptr;        }    }#endif     bool enabled = false;    if (propMap["enabled"].isValid()) {        enabled = propMap["enabled"].toBool();    }     PickFilter filter = PickFilter();    if (propMap["filter"].isValid()) {        filter = getPickFilter(propMap["filter"].toUInt());    }     float maxDistance = 0.0f;    if (propMap["maxDistance"].isValid()) {        maxDistance = propMap["maxDistance"].toFloat();    }     glm::vec3 position = Vectors::ZERO;    if (propMap["position"].isValid()) {        position = vec3FromVariant(propMap["position"]);    } else if (propMap["posOffset"].isValid()) {        position = vec3FromVariant(propMap["posOffset"]);    }     // direction has two defaults to ensure compatibility with older scripts    // Joint ray picks had default direction = Vec3.UP    // Static ray picks had default direction = -Vec3.UP    glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::UP;    if (propMap["orientation"].isValid()) {        direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;    } else if (propMap["direction"].isValid()) {        direction = vec3FromVariant(propMap["direction"]);    } else if (propMap["dirOffset"].isValid()) {        direction = vec3FromVariant(propMap["dirOffset"]);    }     float delayHalf = 0.0f;    if (propMap["delay"].isValid()) {        // We want to be within 0.1% of the target in <delay> seconds        // https://twitter.com/FreyaHolmer/status/1757836988495847568        delayHalf = -std::max(propMap["delay"].toFloat(), 0.0f) / log2f(0.001f);    }     auto rayPick = std::make_shared<RayPick>(position, direction, filter, maxDistance, delayHalf, enabled);    setParentTransform(rayPick, propMap);     return rayPick;} /*@jsdoc * The properties of a stylus pick. * * @typedef {object} Picks.StylusPickProperties * @property {number} [hand=-1] <code>0</code> for the left hand, <code>1</code> for the right hand, invalid (<code>-1</code>)  *     otherwise. * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should *     start disabled. Disabled picks do not update their pick results. * @property {number} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property *     values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. *     <p><strong>Note:</strong> Stylus picks do not intersect avatars or the HUD.</p> * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> *     means no maximum. * @property {Vec3} [tipOffset=0,0.095,0] - The position of the stylus tip relative to the hand position at default avatar  *     scale. * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or  *     {@link Picks.getPickScriptParameters}. A stylus pick's type is {@link PickType.Stylus}. */std::shared_ptr<PickQuery> PickScriptingInterface::buildStylusPick(const QVariantMap& propMap) {    bilateral::Side side = bilateral::Side::Invalid;    {        QVariant handVar = propMap["hand"];        if (handVar.isValid()) {            side = bilateral::side(handVar.toInt());        }    }     bool enabled = false;    if (propMap["enabled"].isValid()) {        enabled = propMap["enabled"].toBool();    }     PickFilter filter = PickFilter();    if (propMap["filter"].isValid()) {        filter = getPickFilter(propMap["filter"].toUInt());    }     float maxDistance = 0.0f;    if (propMap["maxDistance"].isValid()) {        maxDistance = propMap["maxDistance"].toFloat();    }     glm::vec3 tipOffset = TIP_OFFSET;    if (propMap["tipOffset"].isValid()) {        tipOffset = vec3FromVariant(propMap["tipOffset"]);    }     return std::make_shared<StylusPick>(side, filter, maxDistance, enabled, tipOffset);} // NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar // should not be removed from the pick API./*@jsdoc * The properties of a parabola pick. * * @typedef {object} Picks.ParabolaPickProperties * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should  *     start disabled. Disabled picks do not update their pick results. * @property {number} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property  *     values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code>  *     means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint. *     A value of <code>0</code> means no joint. *     <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to  *     the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not  *     parented to anything. *     <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {Vec3} [position=Vec3.ZERO] - The offset of the parabola origin from its parent if parented, otherwise the  *     parabola origin in world coordinates. * @property {Vec3} [posOffset] - Synonym for <code>position</code>. * @property {Vec3} [direction] - The offset of the parabola direction from its parent's y-axis if parented, otherwise the  *     parabola direction in world coordinates. *     <p><strong>Default Value:</strong> <code>Vec3.UP</code> direction if <code>joint</code> is specified, otherwise *     <code>Vec3.FRONT</code>.</p> * @property {Vec3} [dirOffset] - Synonym for <code>direction</code>. * @property {Quat} [orientation] - Alternative property for specifying <code>direction</code>. The value is applied to the  *     default <code>direction</code> value. * @property {number} [speed=1] - The initial speed of the parabola in m/s, i.e., the initial speed of a virtual projectile  *     whose trajectory defines the parabola. * @property {Vec3} [accelerationAxis=-Vec3.UP] - The acceleration of the parabola in m/s<sup>2</sup>, i.e., the acceleration *     of a virtual projectile whose trajectory defines the parabola, both magnitude and direction. * @property {boolean} [rotateAccelerationWithAvatar=true] - <code>true</code> if the acceleration axis should rotate with the *     avatar about the avatar's y-axis, <code>false</code> if it shouldn't. * @property {boolean} [rotateAccelerationWithParent=false] - <code>true</code> if the acceleration axis should rotate with the *     parent about the parent's y-axis, if available. * @property {boolean} [scaleWithParent=true] - <code>true</code> if the velocity and acceleration of the pick should scale *     with the avatar or other parent. * @property {boolean} [scaleWithAvatar=true] - Synonym for <code>scalewithParent</code>. *     <p class="important">Deprecated: This property is deprecated and will be removed.</p> * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or  *     {@link Picks.getPickScriptParameters}. A parabola pick's type is {@link PickType.Parabola}. * @property {Vec3} baseScale - Returned from {@link Picks.getPickProperties} when the pick has a parent with varying scale  *     (usually an avatar or an entity). Its value is the original scale of the parent at the moment the pick was created, and  *     is used to rescale the pick and the pointer which owns this pick, if any. */std::shared_ptr<PickQuery> PickScriptingInterface::buildParabolaPick(const QVariantMap& propMap) {    bool enabled = false;    if (propMap["enabled"].isValid()) {        enabled = propMap["enabled"].toBool();    }     PickFilter filter = PickFilter();    if (propMap["filter"].isValid()) {        filter = getPickFilter(propMap["filter"].toUInt());    }     float maxDistance = 0.0f;    if (propMap["maxDistance"].isValid()) {        maxDistance = propMap["maxDistance"].toFloat();    }     float speed = 1.0f;    if (propMap["speed"].isValid()) {        speed = propMap["speed"].toFloat();    }     glm::vec3 accelerationAxis = -Vectors::UP;    if (propMap["accelerationAxis"].isValid()) {        accelerationAxis = vec3FromVariant(propMap["accelerationAxis"]);    }     bool rotateAccelerationWithAvatar = true;    if (propMap["rotateAccelerationWithAvatar"].isValid()) {        rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();    }     bool rotateAccelerationWithParent = false;    if (propMap["rotateAccelerationWithParent"].isValid()) {        rotateAccelerationWithParent = propMap["rotateAccelerationWithParent"].toBool();    }     bool scaleWithParent = true;    if (propMap["scaleWithParent"].isValid()) {        scaleWithParent = propMap["scaleWithParent"].toBool();    } else if (propMap["scaleWithAvatar"].isValid()) {        scaleWithParent = propMap["scaleWithAvatar"].toBool();    }     glm::vec3 position = Vectors::ZERO;    glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::FRONT;    if (propMap["position"].isValid()) {        position = vec3FromVariant(propMap["position"]);    } else if (propMap["posOffset"].isValid()) {        position = vec3FromVariant(propMap["posOffset"]);    }    if (propMap["orientation"].isValid()) {        direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;    } else if (propMap["direction"].isValid()) {        direction = vec3FromVariant(propMap["direction"]);    } else if (propMap["dirOffset"].isValid()) {        direction = vec3FromVariant(propMap["dirOffset"]);    }     auto parabolaPick = std::make_shared<ParabolaPick>(position, direction, speed, accelerationAxis,        rotateAccelerationWithAvatar, rotateAccelerationWithParent, scaleWithParent, filter, maxDistance, enabled);    setParentTransform(parabolaPick, propMap);    return parabolaPick;}  /*@jsdoc * The properties of a collision pick. * * @typedef {object} Picks.CollisionPickProperties * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should *     start disabled. Disabled picks do not update their pick results. * @property {FilterFlags} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property *     values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. *     <p><strong>Note:</strong> Collision picks do not intersect the HUD.</p> * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> *     means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint. *     A value of <code>0</code> means no joint. *     <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to *     the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not *     parented to anything. *     <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {boolean} [scaleWithParent=true] - <code>true</code> to scale the pick's dimensions and threshold according to the  *     scale of the parent. * * @property {Shape} shape - The collision region's shape and size. Dimensions are in world coordinates but scale with the  *     parent if defined. * @property {Vec3} position - The position of the collision region, relative to the parent if defined. * @property {Quat} orientation - The orientation of the collision region, relative to the parent if defined. * @property {number} threshold - The approximate minimum penetration depth for a test object to be considered in contact with *     the collision region. The depth is in world coordinates but scales with the parent if defined. * @property {CollisionMask} [collisionGroup=8] - The type of objects the collision region collides as. Objects whose collision *     masks overlap with the region's collision group are considered to be colliding with the region. * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or  *     {@link Picks.getPickScriptParameters}. A collision pick's type is {@link PickType.Collision}. * @property {Vec3} baseScale - Returned from {@link Picks.getPickProperties} when the pick has a parent with varying scale  *     (usually an avatar or an entity). Its value is the original scale of the parent at the moment the pick was created, and  *     is used to rescale the pick, and/or the pointer which owns this pick, if any. */std::shared_ptr<PickQuery> PickScriptingInterface::buildCollisionPick(const QVariantMap& propMap) {    bool enabled = false;    if (propMap["enabled"].isValid()) {        enabled = propMap["enabled"].toBool();    }     PickFilter filter = PickFilter();    if (propMap["filter"].isValid()) {        filter = getPickFilter(propMap["filter"].toUInt());    }     float maxDistance = 0.0f;    if (propMap["maxDistance"].isValid()) {        maxDistance = propMap["maxDistance"].toFloat();    }     bool scaleWithParent = true;    if (propMap["scaleWithParent"].isValid()) {        scaleWithParent = propMap["scaleWithParent"].toBool();    }     CollisionRegion collisionRegion(propMap);    auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, scaleWithParent, collisionRegion, qApp->getPhysicsEngine());    setParentTransform(collisionPick, propMap);     return collisionPick;} void PickScriptingInterface::enablePick(unsigned int uid) {    DependencyManager::get<PickManager>()->enablePick(uid);} void PickScriptingInterface::disablePick(unsigned int uid) {    DependencyManager::get<PickManager>()->disablePick(uid);} bool PickScriptingInterface::isPickEnabled(unsigned int uid) const {    return DependencyManager::get<PickManager>()->isPickEnabled(uid);} void PickScriptingInterface::removePick(unsigned int uid) {    DependencyManager::get<PickManager>()->removePick(uid);} QVariantMap PickScriptingInterface::getPickProperties(unsigned int uid) const {    return DependencyManager::get<PickManager>()->getPickProperties(uid);} QVariantMap PickScriptingInterface::getPickScriptParameters(unsigned int uid) const {    return DependencyManager::get<PickManager>()->getPickScriptParameters(uid);} QVector<unsigned int> PickScriptingInterface::getPicks() const {    return DependencyManager::get<PickManager>()->getPicks();} QVariantMap PickScriptingInterface::getPrevPickResult(unsigned int uid) {    QVariantMap result;    auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResult(uid);    if (pickResult) {        result = pickResult->toVariantMap();    }    return result;} void PickScriptingInterface::setPrecisionPicking(unsigned int uid, bool precisionPicking) {    DependencyManager::get<PickManager>()->setPrecisionPicking(uid, precisionPicking);} void PickScriptingInterface::setIgnoreItems(unsigned int uid, const ScriptValue& ignoreItems) {    DependencyManager::get<PickManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));} void PickScriptingInterface::setIncludeItems(unsigned int uid, const ScriptValue& includeItems) {    DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));} void PickScriptingInterface::setDelay(unsigned int uid, float delay) {    DependencyManager::get<PickManager>()->setDelay(uid, delay);} bool PickScriptingInterface::isLeftHand(unsigned int uid) {    return DependencyManager::get<PickManager>()->isLeftHand(uid);} bool PickScriptingInterface::isRightHand(unsigned int uid) {    return DependencyManager::get<PickManager>()->isRightHand(uid);} bool PickScriptingInterface::isMouse(unsigned int uid) {    return DependencyManager::get<PickManager>()->isMouse(uid);} ScriptValue pickTypesToScriptValue(ScriptEngine* engine, const PickQuery::PickType& pickType) {    return engine->newValue(pickType);} bool pickTypesFromScriptValue(const ScriptValue& object, PickQuery::PickType& pickType) {    pickType = static_cast<PickQuery::PickType>(object.toUInt16());    return true;} void PickScriptingInterface::registerMetaTypes(ScriptEngine* engine) {    scriptRegisterMetaType<PickQuery::PickType, pickTypesToScriptValue, pickTypesFromScriptValue>(engine);} void PickScriptingInterface::registerProperties(ScriptEngine* engine) {    ScriptValue pickTypes = engine->newObject();    auto metaEnum = QMetaEnum::fromType<PickQuery::PickType>();    for (int i = 0; i < PickQuery::PickType::NUM_PICK_TYPES; ++i) {        pickTypes.setProperty(metaEnum.key(i), metaEnum.value(i));

Lines 1–500 of 582.