665 lines · 28.0 KB · C
RawDownload
////  RegisteredMetaTypes.h//  libraries/shared/src////  Created by Stephen Birarda on 10/3/13.//  Copyright 2013 High Fidelity, Inc.//  Copyright 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// #ifndef hifi_RegisteredMetaTypes_h#define hifi_RegisteredMetaTypes_h #include <QtCore/QUuid>#include <QtCore/QUrl>#include <QtGlobal> #include <glm/glm.hpp>#include <glm/gtc/quaternion.hpp> #include "AACube.h"#include "ShapeInfo.h"#include "SharedUtil.h"#include "shared/Bilateral.h"#include "Transform.h"#include "PhysicsCollisionGroups.h"#include "StencilMaskMode.h" class QColor;class QUrl; Q_DECLARE_METATYPE(uint16_t)Q_DECLARE_METATYPE(glm::vec2)Q_DECLARE_METATYPE(glm::u8vec3)Q_DECLARE_METATYPE(glm::vec3)Q_DECLARE_METATYPE(glm::vec4)Q_DECLARE_METATYPE(glm::quat)Q_DECLARE_METATYPE(glm::mat4)Q_DECLARE_METATYPE(QVector<float>)Q_DECLARE_METATYPE(unsigned int)Q_DECLARE_METATYPE(QVector<unsigned int>)Q_DECLARE_METATYPE(AACube)Q_DECLARE_METATYPE(std::function<void()>);Q_DECLARE_METATYPE(std::function<QVariant()>); // Mat4/*@jsdoc * A 4 x 4 matrix, typically containing a scale, rotation, and translation transform. See also the {@link Mat4(0)|Mat4} object. * * @typedef {object} Mat4 * @property {number} r0c0 - Row 0, column 0 value. * @property {number} r1c0 - Row 1, column 0 value. * @property {number} r2c0 - Row 2, column 0 value. * @property {number} r3c0 - Row 3, column 0 value. * @property {number} r0c1 - Row 0, column 1 value. * @property {number} r1c1 - Row 1, column 1 value. * @property {number} r2c1 - Row 2, column 1 value. * @property {number} r3c1 - Row 3, column 1 value. * @property {number} r0c2 - Row 0, column 2 value. * @property {number} r1c2 - Row 1, column 2 value. * @property {number} r2c2 - Row 2, column 2 value. * @property {number} r3c2 - Row 3, column 2 value. * @property {number} r0c3 - Row 0, column 3 value. * @property {number} r1c3 - Row 1, column 3 value. * @property {number} r2c3 - Row 2, column 3 value. * @property {number} r3c3 - Row 3, column 3 value. */QVariant mat4ToVariant(const glm::mat4& mat4);glm::mat4 mat4FromVariant(const QVariant& object, bool& valid);glm::mat4 mat4FromVariant(const QVariant& object); /*@jsdoc* A 2-dimensional vector.** @typedef {object} Vec2* @property {number} x - X-coordinate of the vector. Synonyms: <code>u</code>.* @property {number} y - Y-coordinate of the vector. Synonyms: <code>v</code>.* @example <caption>Vec2s can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption>* Entities.editEntity(<id>, { materialMappingPos: { x: 0.1, y: 0.2 }});          // { x: 0.1, y: 0.2 }* Entities.editEntity(<id>, { materialMappingPos: { u: 0.3, v: 0.4 }});          // { x: 0.3, y: 0.4 }* Entities.editEntity(<id>, { materialMappingPos: [0.5, 0.6] });                 // { x: 0.5, y: 0.6 }* Entities.editEntity(<id>, { materialMappingPos: 0.7 });                        // { x: 0.7, y: 0.7 }* var color = Entities.getEntityProperties(<id>).materialMappingPos;             // { x: 0.7, y: 0.7 }* color.v = 0.8;                                                                 // { x: 0.7, y: 0.8 }*/QVariant vec2ToVariant(const glm::vec2& vec2);glm::vec2 vec2FromVariant(const QVariant& object, bool& valid);glm::vec2 vec2FromVariant(const QVariant& object); /*@jsdoc* A 3-dimensional vector. See also the {@link Vec3(0)|Vec3} object.** @typedef {object} Vec3* @property {number} x - X-coordinate of the vector. Synonyms: <code>r</code>, <code>red</code>.* @property {number} y - Y-coordinate of the vector. Synonyms: <code>g</code>, <code>green</code>.* @property {number} z - Z-coordinate of the vector. Synonyms: <code>b</code>, <code>blue</code>.* @example <caption>Vec3 values can be set in multiple ways and modified with their aliases, but still stringify in the same *     way.</caption>* Entities.editEntity(<id>, { position: { x: 1, y: 2, z: 3 }});                 // { x: 1, y: 2, z: 3 }* Entities.editEntity(<id>, { position: { r: 4, g: 5, b: 6 }});                 // { x: 4, y: 5, z: 6 }* Entities.editEntity(<id>, { position: { red: 7, green: 8, blue: 9 }});        // { x: 7, y: 8, z: 9 }* Entities.editEntity(<id>, { position: [10, 11, 12] });                        // { x: 10, y: 11, z: 12 }* Entities.editEntity(<id>, { position: 13 });                                  // { x: 13, y: 13, z: 13 }* var position = Entities.getEntityProperties(<id>).position;                   // { x: 13, y: 13, z: 13 }* position.g = 14;                                                              // { x: 13, y: 14, z: 13 }* position.blue = 15;                                                           // { x: 13, y: 14, z: 15 }* Entities.editEntity(<id>, { position: "red"});                                // { x: 255, y: 0, z: 0 }* Entities.editEntity(<id>, { position: "#00FF00"});                            // { x: 0, y: 255, z: 0 }*/QVariant vec3toVariant(const glm::vec3& vec3);glm::vec3 vec3FromVariant(const QVariant &object, bool& valid);glm::vec3 vec3FromVariant(const QVariant &object); /*@jsdoc * A color vector. See also the {@link Vec3(0)|Vec3} object. * * @typedef {object} Color * @property {number} red - Red component value. Integer in the range <code>0</code> - <code>255</code>.  Synonyms: <code>r</code>, <code>x</code>. * @property {number} green - Green component value. Integer in the range <code>0</code> - <code>255</code>.  Synonyms: <code>g</code>, <code>y</code>. * @property {number} blue - Blue component value. Integer in the range <code>0</code> - <code>255</code>.  Synonyms: <code>b</code>, <code>z</code>. * @example <caption>Colors can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption> * Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }});                 // { red: 1, green: 2, blue: 3 } * Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }});                 // { red: 4, green: 5, blue: 6 } * Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }});        // { red: 7, green: 8, blue: 9 } * Entities.editEntity(<id>, { color: [10, 11, 12] });                        // { red: 10, green: 11, blue: 12 } * Entities.editEntity(<id>, { color: 13 });                                  // { red: 13, green: 13, blue: 13 } * var color = Entities.getEntityProperties(<id>).color;                      // { red: 13, green: 13, blue: 13 } * color.g = 14;                                                              // { red: 13, green: 14, blue: 13 } * color.blue = 15;                                                           // { red: 13, green: 14, blue: 15 } * Entities.editEntity(<id>, { color: "red"});                                // { red: 255, green: 0, blue: 0 } * Entities.editEntity(<id>, { color: "#00FF00"});                            // { red: 0, green: 255, blue: 0 } *//*@jsdoc * A color vector with real values. Values may also be <code>null</code>. See also the {@link Vec3(0)|Vec3} object. * * @typedef {object} ColorFloat * @property {number} red - Red component value. Real in the range <code>0</code> - <code>255</code>.  Synonyms: <code>r</code>, <code>x</code>. * @property {number} green - Green component value. Real in the range <code>0</code> - <code>255</code>.  Synonyms: <code>g</code>, <code>y</code>. * @property {number} blue - Blue component value. Real in the range <code>0</code> - <code>255</code>.  Synonyms: <code>b</code>, <code>z</code>. * @example <caption>ColorFloats can be set in multiple ways and modified with their aliases, but still stringify in the same way</caption> * Entities.editEntity(<id>, { color: { x: 1, y: 2, z: 3 }});                 // { red: 1, green: 2, blue: 3 } * Entities.editEntity(<id>, { color: { r: 4, g: 5, b: 6 }});                 // { red: 4, green: 5, blue: 6 } * Entities.editEntity(<id>, { color: { red: 7, green: 8, blue: 9 }});        // { red: 7, green: 8, blue: 9 } * Entities.editEntity(<id>, { color: [10, 11, 12] });                        // { red: 10, green: 11, blue: 12 } * Entities.editEntity(<id>, { color: 13 });                                  // { red: 13, green: 13, blue: 13 } * var color = Entities.getEntityProperties(<id>).color;                      // { red: 13, green: 13, blue: 13 } * color.g = 14;                                                              // { red: 13, green: 14, blue: 13 } * color.blue = 15;                                                           // { red: 13, green: 14, blue: 15 } * Entities.editEntity(<id>, { color: "red"});                                // { red: 255, green: 0, blue: 0 } * Entities.editEntity(<id>, { color: "#00FF00"});                            // { red: 0, green: 255, blue: 0 } */QVariant u8vec3toVariant(const glm::u8vec3& vec3);QVariant u8vec3ColortoVariant(const glm::u8vec3& vec3);glm::u8vec3 u8vec3FromVariant(const QVariant &object, bool& valid);glm::u8vec3 u8vec3FromVariant(const QVariant &object); /*@jsdoc * A 4-dimensional vector. * * @typedef {object} Vec4 * @property {number} x - X-coordinate of the vector. * @property {number} y - Y-coordinate of the vector. * @property {number} z - Z-coordinate of the vector. * @property {number} w - W-coordinate of the vector. */QVariant vec4toVariant(const glm::vec4& vec4);glm::vec4 vec4FromVariant(const QVariant &object, bool& valid);glm::vec4 vec4FromVariant(const QVariant &object); // QuaternionsQVariant quatToVariant(const glm::quat& quat);glm::quat quatFromVariant(const QVariant &object, bool& isValid);glm::quat quatFromVariant(const QVariant &object); /*@jsdoc * Defines a rectangular portion of an image or screen, or similar. * @typedef {object} Rect * @property {number} x - Left, x-coordinate value. * @property {number} y - Top, y-coordinate value. * @property {number} width - Width of the rectangle. * @property {number} height - Height of the rectangle. */QRect qRectFromVariant(const QVariant& object, bool& isValid);QRect qRectFromVariant(const QVariant& object);QVariant qRectToVariant(const QRect& rect); QRectF qRectFFromVariant(const QVariant& object, bool& isValid);QRectF qRectFFromVariant(const QVariant& object);QVariant qRectFToVariant(const QRectF& rect); // MathPicks also have to overide operator== for their typeclass MathPick {public:    virtual ~MathPick() {}    virtual operator bool() const = 0;    virtual QVariantMap toVariantMap() const = 0;}; /*@jsdoc * A vector with a starting point. It is used, for example, when finding entities or avatars that lie under a mouse click or  * intersect a laser beam. * * @typedef {object} PickRay * @property {Vec3} origin - The starting position of the ray. * @property {Vec3} direction - The direction that the ray travels. * @property {Vec3} unmodifiedDirection - The direction that the ray would travel, if not for applied effects like delays. */class PickRay : public MathPick {public:    PickRay() : origin(NAN), direction(NAN), unmodifiedDirection(NAN)  { }    PickRay(const QVariantMap& pickVariant) :        origin(vec3FromVariant(pickVariant["origin"])), direction(vec3FromVariant(pickVariant["direction"])),        unmodifiedDirection(vec3FromVariant(pickVariant["unmodifiedDirection"])) {}    PickRay(const glm::vec3& origin, const glm::vec3& direction) :        origin(origin), direction(direction), unmodifiedDirection(direction) {}    PickRay(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& unmodifiedDirection) :        origin(origin), direction(direction), unmodifiedDirection(unmodifiedDirection) {}    glm::vec3 origin;    glm::vec3 direction;    glm::vec3 unmodifiedDirection;     operator bool() const override {        return !(glm::any(glm::isnan(origin)) || glm::any(glm::isnan(direction)) || glm::any(glm::isnan(unmodifiedDirection)));    }    bool operator==(const PickRay& other) const {        return (origin == other.origin && direction == other.direction && unmodifiedDirection == other.unmodifiedDirection);    }    QVariantMap toVariantMap() const override {        QVariantMap pickRay;        pickRay["origin"] = vec3toVariant(origin);        pickRay["direction"] = vec3toVariant(direction);        pickRay["unmodifiedDirection"] = vec3toVariant(unmodifiedDirection);        return pickRay;    }};Q_DECLARE_METATYPE(PickRay) /*@jsdoc * The tip of a stylus. * * @typedef {object} StylusTip * @property {number} side - The hand that the stylus is attached to: <code>0</code> for left hand, <code>1</code> for the  *     right hand, <code>-1</code> for invalid. * @property {Vec3} tipOffset - The position of the stylus tip relative to the body of the stylus. * @property {Vec3} position - The position of the stylus tip. * @property {Quat} orientation - The orientation of the stylus. * @property {Vec3} velocity - The velocity of the stylus tip. */class StylusTip : public MathPick {public:    StylusTip() : position(NAN), velocity(NAN) {}    StylusTip(const bilateral::Side& side, const glm::vec3& tipOffset = Vectors::ZERO ,const glm::vec3& position = Vectors::ZERO,              const glm::quat& orientation = Quaternions::IDENTITY, const glm::vec3& velocity = Vectors::ZERO) :        side(side), tipOffset(tipOffset), position(position), orientation(orientation), velocity(velocity) {}    StylusTip(const QVariantMap& pickVariant) : side(bilateral::Side(pickVariant["side"].toInt())), tipOffset(vec3FromVariant(pickVariant["tipOffset"])),        position(vec3FromVariant(pickVariant["position"])), orientation(quatFromVariant(pickVariant["orientation"])), velocity(vec3FromVariant(pickVariant["velocity"])) {}     bilateral::Side side { bilateral::Side::Invalid };    glm::vec3 tipOffset;    glm::vec3 position;    glm::quat orientation;    glm::vec3 velocity;     operator bool() const override { return side != bilateral::Side::Invalid; }     bool operator==(const StylusTip& other) const {        return (side == other.side && tipOffset == other.tipOffset && position == other.position && orientation == other.orientation && velocity == other.velocity);    }     QVariantMap toVariantMap() const override {        QVariantMap stylusTip;        stylusTip["side"] = (int)side;        stylusTip["tipOffset"] = vec3toVariant(tipOffset);        stylusTip["position"] = vec3toVariant(position);        stylusTip["orientation"] = quatToVariant(orientation);        stylusTip["velocity"] = vec3toVariant(velocity);        return stylusTip;    }}; /*@jsdoc* A parabola defined by a starting point, initial velocity, and acceleration. It is used, for example, when finding entities or* avatars that intersect a parabolic beam.** @typedef {object} PickParabola* @property {Vec3} origin - The starting position of the parabola, i.e., the initial position of a virtual projectile whose *     trajectory defines the parabola.* @property {Vec3} velocity - The starting velocity of the parabola in m/s, i.e., the initial speed of a virtual projectile *     whose trajectory defines the parabola.* @property {Vec3} acceleration - The acceleration that the parabola experiences in m/s<sup>2</sup>, i.e., the acceleration of *     a virtual projectile whose trajectory defines the parabola, both magnitude and direction.*/class PickParabola : public MathPick {public:    PickParabola() : origin(NAN), velocity(NAN), acceleration(NAN) { }    PickParabola(const QVariantMap& pickVariant) : origin(vec3FromVariant(pickVariant["origin"])), velocity(vec3FromVariant(pickVariant["velocity"])), acceleration(vec3FromVariant(pickVariant["acceleration"])) {}    PickParabola(const glm::vec3& origin, const glm::vec3 velocity, const glm::vec3 acceleration) : origin(origin), velocity(velocity), acceleration(acceleration) {}    glm::vec3 origin;    glm::vec3 velocity;    glm::vec3 acceleration;     operator bool() const override {        return !(glm::any(glm::isnan(origin)) || glm::any(glm::isnan(velocity)) || glm::any(glm::isnan(acceleration)));    }    bool operator==(const PickParabola& other) const {        return (origin == other.origin && velocity == other.velocity && acceleration == other.acceleration);    }    QVariantMap toVariantMap() const override {        QVariantMap pickParabola;        pickParabola["origin"] = vec3toVariant(origin);        pickParabola["velocity"] = vec3toVariant(velocity);        pickParabola["acceleration"] = vec3toVariant(acceleration);        return pickParabola;    }}; class CollisionRegion : public MathPick {public:    CollisionRegion() { }     CollisionRegion(const CollisionRegion& collisionRegion) :        loaded(collisionRegion.loaded),        modelURL(collisionRegion.modelURL),        shapeInfo(std::make_shared<ShapeInfo>()),        transform(collisionRegion.transform),        threshold(collisionRegion.threshold),        collisionGroup(collisionRegion.collisionGroup)    {        shapeInfo->setParams(collisionRegion.shapeInfo->getType(), collisionRegion.shapeInfo->getHalfExtents(), collisionRegion.modelURL.toString());    }     CollisionRegion(const QVariantMap& pickVariant) {        // "loaded" is not deserialized here because there is no way to know if the shape is actually loaded        if (pickVariant["shape"].isValid()) {            auto shape = pickVariant["shape"].toMap();            if (!shape.empty()) {                ShapeType shapeType = SHAPE_TYPE_NONE;                if (shape["shapeType"].isValid()) {                    shapeType = ShapeInfo::getShapeTypeForName(shape["shapeType"].toString());                }                if (shapeType >= SHAPE_TYPE_COMPOUND && shapeType <= SHAPE_TYPE_STATIC_MESH && shape["modelURL"].isValid()) {                    QString newURL = shape["modelURL"].toString();                    modelURL.setUrl(newURL);                } else {                    modelURL.setUrl("");                }                 if (shape["dimensions"].isValid()) {                    transform.setScale(vec3FromVariant(shape["dimensions"]));                }                 shapeInfo->setParams(shapeType, transform.getScale() / 2.0f, modelURL.toString());            }        }         if (pickVariant["threshold"].isValid()) {            threshold = glm::max(0.0f, pickVariant["threshold"].toFloat());        }         if (pickVariant["position"].isValid()) {            transform.setTranslation(vec3FromVariant(pickVariant["position"]));        }        if (pickVariant["orientation"].isValid()) {            transform.setRotation(quatFromVariant(pickVariant["orientation"]));        }        if (pickVariant["collisionGroup"].isValid()) {            collisionGroup = pickVariant["collisionGroup"].toUInt();        }    }     /*@jsdoc     * A volume for checking collisions in the physics simulation.     * @typedef {object} CollisionRegion     * @property {Shape} shape - The collision region's shape and size. Dimensions are in world coordinates, but scale with the      *     parent if defined.     * @property {boolean} loaded - <code>true</code> if the <code>shape</code> has no model, or has a model and it is loaded,      *     <code>false</code> if otherwise.     * @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.     */     /*@jsdoc     * A physical volume.     * @typedef {object} Shape     * @property {ShapeType} shapeType="none" - The type of shape.     * @property {string} [modelUrl=""] - The model to load to for the shape if <code>shapeType</code> is one of     *     <code>"compound"</code>, <code>"simple-hull"</code>, <code>"simple-compound"</code>, or <code>"static-mesh"</code>.     * @property {Vec3} dimensions - The dimensions of the shape.     */     QVariantMap toVariantMap() const override {        QVariantMap collisionRegion;         QVariantMap shape;        shape["shapeType"] = ShapeInfo::getNameForShapeType(shapeInfo->getType());        shape["modelURL"] = modelURL.toString();        shape["dimensions"] = vec3toVariant(transform.getScale());         collisionRegion["shape"] = shape;        collisionRegion["loaded"] = loaded;         collisionRegion["threshold"] = threshold;        collisionRegion["collisionGroup"] = collisionGroup;         collisionRegion["position"] = vec3toVariant(transform.getTranslation());        collisionRegion["orientation"] = quatToVariant(transform.getRotation());         return collisionRegion;    }     operator bool() const override {        return !std::isnan(threshold) &&            !(glm::any(glm::isnan(transform.getTranslation())) ||            glm::any(glm::isnan(transform.getRotation())) ||            shapeInfo->getType() == SHAPE_TYPE_NONE ||            collisionGroup == 0);    }     bool operator==(const CollisionRegion& other) const {        return loaded == other.loaded &&            threshold == other.threshold &&            collisionGroup == other.collisionGroup &&            glm::all(glm::equal(transform.getTranslation(), other.transform.getTranslation())) &&            glm::all(glm::equal(transform.getRotation(), other.transform.getRotation())) &&            glm::all(glm::equal(transform.getScale(), other.transform.getScale())) &&            shapeInfo->getType() == other.shapeInfo->getType() &&            modelURL == other.modelURL;    }     bool shouldComputeShapeInfo() const {        if (!(shapeInfo->getType() == SHAPE_TYPE_HULL ||            (shapeInfo->getType() >= SHAPE_TYPE_COMPOUND &&                shapeInfo->getType() <= SHAPE_TYPE_STATIC_MESH)            )) {            return false;        }         if (collisionGroup == 0) {            return false;        }         return !shapeInfo->getPointCollection().size();    }     // We can't load the model here because it would create a circular dependency, so we delegate that responsibility to the owning CollisionPick    bool loaded { false };    QUrl modelURL;     // We can't compute the shapeInfo here without loading the model first, so we delegate that responsibility to the owning CollisionPick    std::shared_ptr<ShapeInfo> shapeInfo = std::make_shared<ShapeInfo>();    Transform transform;    float threshold { 0.0f };    uint16_t collisionGroup { USER_COLLISION_GROUP_MY_AVATAR };}; inline void hash_combine(std::size_t& seed) {    Q_UNUSED(seed);} template <typename T, typename... Rest>inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {    std::hash<T> hasher;    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);    hash_combine(seed, rest...);} template <>struct std::hash<bilateral::Side> {    size_t operator()(const bilateral::Side& a) const { return std::hash<int>()((int)a); }}; template <>struct std::hash<glm::vec3> {    size_t operator()(const glm::vec3& a) const {        size_t result = 0;        hash_combine(result, a.x, a.y, a.z);        return result;    }}; template <>struct std::hash<glm::quat> {    size_t operator()(const glm::quat& a) const {        size_t result = 0;        hash_combine(result, a.x, a.y, a.z, a.w);        return result;    }}; template <>struct std::hash<Transform> {    size_t operator()(const Transform& a) const {        size_t result = 0;

Lines 1–500 of 665.