IT'S BUILDING (but still wip)

This commit is contained in:
SamGondelman 2019-01-25 14:04:52 -08:00
parent 5ce8f566cc
commit a2083d949e
17 changed files with 269 additions and 360 deletions

View file

@ -8748,7 +8748,7 @@ void Application::createLoginDialog() {
EntityItemProperties properties;
properties.setType(EntityTypes::Web);
properties.setName("LoginDialogEntity");
properties.setSourceUrl(LOGIN_DIALOG);
properties.setSourceUrl(LOGIN_DIALOG.toString());
properties.setPosition(position);
properties.setRotation(cameraOrientation);
properties.setDimensions(LOGIN_DIMENSIONS);

View file

@ -57,7 +57,7 @@ protected:
void onRemoveAttachedAvatarEntity(const QUuid& id);
std::vector<QUuid> _attachedAvatarEntities;
QUuid _otherAvatarOrbMeshPlaceholderID { UNKNOWN_ENTITY_ID };
QUuid _otherAvatarOrbMeshPlaceholderID;
AvatarMotionState* _motionState { nullptr };
int32_t _spaceIndex { -1 };
uint8_t _workloadRegion { workload::Region::INVALID };

View file

@ -10,6 +10,8 @@
#include "PathPointer.h"
#include <render/Item.h>
class ParabolaPointer : public PathPointer {
using Parent = PathPointer;
public:

View file

@ -102,6 +102,11 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3
}
glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) {
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
EntityPropertyFlags desiredProperties;
desiredProperties += PROP_POSITION;
desiredProperties += PROP_ROTATION;
desiredProperties += PROP_DIMENSIONS;
desiredProperties += PROP_REGISTRATION_POINT;
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID, desiredProperties);
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized);
}

View file

@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() {
tablet->gotoHomeScreen();
hmd->closeTablet();
}
qApp->setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID);
qApp->setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID);
setAddressBarVisible(false);
}

View file

@ -302,7 +302,7 @@ void Base3DOverlay::locationChanged(bool tellPhysics) {
// FIXME: Overlays shouldn't be deleted when their parents are
void Base3DOverlay::parentDeleted() {
qApp->getOverlays().deleteOverlay(getOverlayID());
qApp->getOverlays().deleteOverlay(Overlay::getID());
}
void Base3DOverlay::update(float duration) {

View file

@ -27,15 +27,9 @@ public:
void setVisible(bool visible) override;
bool queryAACubeNeedsUpdate() const override { return false; } // HACK: queryAACube not relevant for Overlays
virtual OverlayID getOverlayID() const override { return OverlayID(getID().toString()); }
void setOverlayID(OverlayID overlayID) override { setID(overlayID); }
virtual QString getName() const override;
void setName(QString name);
// getters
virtual bool is3D() const override { return true; }
virtual render::ItemKey getKey() override;
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); }
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }

View file

@ -249,17 +249,17 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt
return ContextOverlayInterface::destroyContextOverlay(entityItemID, PointerEvent());
}
void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
if (overlayID == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) {
qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "Overlay ID:" << overlayID;
void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) {
qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id;
emit contextOverlayClicked(_currentEntityWithContextOverlay);
_contextOverlayJustClicked = true;
}
}
void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) {
void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event) {
if (_contextOverlayID != UNKNOWN_ENTITY_ID) {
qCDebug(context_overlay) << "Started hovering over Context Overlay. Overlay ID:" << overlayID;
qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id;
EntityItemProperties properties;
properties.setColor(CONTEXT_OVERLAY_COLOR);
properties.getPulse().setColorMode(PulseMode::NONE);
@ -269,9 +269,9 @@ void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const OverlayID&
}
}
void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) {
void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event) {
if (_contextOverlayID != UNKNOWN_ENTITY_ID) {
qCDebug(context_overlay) << "Stopped hovering over Context Overlay. Overlay ID:" << overlayID;
qCDebug(context_overlay) << "Stopped hovering over Context Overlay. ID:" << id;
EntityItemProperties properties;
properties.setColor(CONTEXT_OVERLAY_COLOR);
properties.getPulse().setColorMode(PulseMode::IN_PHASE);
@ -281,17 +281,17 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID&
}
}
void ContextOverlayInterface::contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event) {
void ContextOverlayInterface::contextOverlays_hoverEnterEntity(const EntityItemID& id, const PointerEvent& event) {
bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get<PointerManager>()->isMouse(event.getID());
if (contextOverlayFilterPassed(entityID) && _enabled && !isMouse) {
enableEntityHighlight(entityID);
if (contextOverlayFilterPassed(id) && _enabled && !isMouse) {
enableEntityHighlight(id);
}
}
void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event) {
void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemID& id, const PointerEvent& event) {
bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get<PointerManager>()->isMouse(event.getID());
if (_currentEntityWithContextOverlay != entityID && _enabled && !isMouse) {
disableEntityHighlight(entityID);
if (_currentEntityWithContextOverlay != id && _enabled && !isMouse) {
disableEntityHighlight(id);
}
}
@ -388,12 +388,12 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID
}
}
void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityItemID) {
_selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID);
void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityID) {
_selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
}
void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityItemID) {
_selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID);
void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityID) {
_selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
}
void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) {

View file

@ -65,9 +65,9 @@ public slots:
bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
bool destroyContextOverlay(const EntityItemID& entityItemID);
void contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
void contextOverlays_hoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event);
void contextOverlays_hoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event);
void contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event);
void contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event);
void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event);
void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event);
void contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event);
bool contextOverlayFilterPassed(const EntityItemID& entityItemID);

View file

@ -189,7 +189,7 @@ scriptable::ScriptableModelBase Cube3DOverlay::getScriptableModel() {
auto vertexColor = ColorUtils::toVec3(_color);
scriptable::ScriptableModelBase result;
if (auto mesh = geometryCache->meshFromShape(GeometryCache::Cube, vertexColor)) {
result.objectID = getID();
result.objectID = Overlay::getID();
result.append(mesh);
}
return result;

View file

@ -92,7 +92,7 @@ void ModelOverlay::update(float deltatime) {
render::ScenePointer scene = qApp->getMain3DScene();
render::Transaction transaction;
if (_model->needsFixupInScene()) {
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getID(), NestableType::Overlay, _model);
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model);
_model->removeFromScene(scene, transaction);
_model->addToScene(scene, transaction);
@ -101,8 +101,7 @@ void ModelOverlay::update(float deltatime) {
auto modelOverlay = static_cast<ModelOverlay*>(&data);
modelOverlay->setSubRenderItemIDs(newRenderItemIDs);
});
processMaterials();
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getID(), NestableType::Overlay, _model);
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model);
}
bool metaDirty = false;
if (_visibleDirty && _texturesLoaded) {
@ -145,15 +144,14 @@ void ModelOverlay::update(float deltatime) {
bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
Volume3DOverlay::addToScene(overlay, scene, transaction);
_model->addToScene(scene, transaction);
processMaterials();
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getID(), NestableType::Overlay, _model);
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model);
return true;
}
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);
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model);
transaction.updateItem<Overlay>(getRenderItemID(), [](Overlay& data) {
auto modelOverlay = static_cast<ModelOverlay*>(&data);
modelOverlay->clearSubRenderItemIDs();
@ -709,32 +707,6 @@ uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const {
return 0;
}
void ModelOverlay::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
Overlay::addMaterial(material, parentMaterialName);
if (_model && _model->fetchRenderItemIDs().size() > 0) {
_model->addMaterial(material, parentMaterialName);
}
}
void ModelOverlay::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
Overlay::removeMaterial(material, parentMaterialName);
if (_model && _model->fetchRenderItemIDs().size() > 0) {
_model->removeMaterial(material, parentMaterialName);
}
}
void ModelOverlay::processMaterials() {
assert(_model);
std::lock_guard<std::mutex> lock(_materialsLock);
for (auto& shapeMaterialPair : _materials) {
auto material = shapeMaterialPair.second;
while (!material.empty()) {
_model->addMaterial(material.top(), shapeMaterialPair.first);
material.pop();
}
}
}
bool ModelOverlay::canReplaceModelMeshPart(int meshIndex, int partIndex) {
// TODO: bounds checking; for now just used to indicate provider generally supports mesh updates
return _model && _model->isLoaded();
@ -750,11 +722,7 @@ scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() {
return Base3DOverlay::getScriptableModel();
}
auto result = _model->getScriptableModel();
result.objectID = getID();
{
std::lock_guard<std::mutex> lock(_materialsLock);
result.appendMaterials(_materials);
}
result.objectID = Overlay::getID();
return result;
}

View file

@ -70,9 +70,6 @@ public:
void setDrawHUDLayer(bool drawHUDLayer) override;
void setGroupCulled(bool groupCulled);
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override;
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override;
virtual scriptable::ScriptableModelBase getScriptableModel() override;
virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override;
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override;
@ -130,8 +127,6 @@ private:
bool _isGroupCulled { false };
bool _groupCulledDirty { false };
void processMaterials();
};
#endif // hifi_ModelOverlay_h

View file

@ -24,8 +24,6 @@ public:
virtual AABox getBounds() const override;
virtual bool is3D() const override { return false; }
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return 1; }
// getters

View file

@ -21,20 +21,15 @@
#include "Application.h"
#include "InterfaceLogging.h"
#include "Image3DOverlay.h"
#include "Circle3DOverlay.h"
#include "Cube3DOverlay.h"
#include "Shape3DOverlay.h"
#include "ImageOverlay.h"
#include "Line3DOverlay.h"
#include "ModelOverlay.h"
#include "Rectangle3DOverlay.h"
#include "Sphere3DOverlay.h"
#include "Grid3DOverlay.h"
#include "TextOverlay.h"
#include "RectangleOverlay.h"
#include "Text3DOverlay.h"
#include "Web3DOverlay.h"
#include <raypick/RayPick.h>
#include <RenderableWebEntityItem.h>
#include "ui/Keyboard.h"
#include <QtQuick/QQuickWindow>
@ -42,6 +37,9 @@
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
std::unordered_map<QString, QString> Overlays::_entityToOverlayTypes;
std::unordered_map<QString, QString> Overlays::_overlayToEntityTypes;
Overlays::Overlays() {
auto pointerManager = DependencyManager::get<PointerManager>();
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent);
@ -50,6 +48,17 @@ Overlays::Overlays() {
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, this, &Overlays::mousePressPointerEvent);
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent);
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleasePointerEvent);
ADD_TYPE_MAP(Box, cube);
ADD_TYPE_MAP(Sphere, sphere);
ADD_TYPE_MAP(Shape, shape);
ADD_TYPE_MAP(Model, model);
ADD_TYPE_MAP(Text, text3d);
ADD_TYPE_MAP(Image, image3d);
ADD_TYPE_MAP(Web, web3d);
ADD_TYPE_MAP(PolyLine, line3d);
ADD_TYPE_MAP(Grid, grid);
ADD_TYPE_MAP(Gizmo, circle3d);
}
void Overlays::cleanupAllOverlays() {
@ -151,9 +160,39 @@ Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const {
return nullptr;
}
QString Overlays::entityToOverlayType(const QString& type) {
auto iter = _entityToOverlayTypes.find(type);
if (iter != _entityToOverlayTypes.end()) {
return iter->second;
}
return "unknown";
}
QString Overlays::overlayToEntityType(const QString& type) {
auto iter = _overlayToEntityTypes.find(type);
if (iter != _overlayToEntityTypes.end()) {
return iter->second;
} else if (type == "billboard") {
return "Image";
}
return "Unknown";
}
EntityItemProperties convertOverlayToEntityProperties(const QVariantMap& overlayProps) {
EntityItemProperties props;
return props;
}
QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps) {
QVariantMap props;
return props;
}
QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
return UNKNOWN_ENTITY_ID;
}
if (QThread::currentThread() != thread()) {
@ -163,8 +202,6 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
return result;
}
Overlay::Pointer thisOverlay = nullptr;
/**jsdoc
* <p>An overlay may be one of the following types:</p>
* <table>
@ -172,26 +209,26 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
* <tr><th>Value</th><th>2D/3D</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>image</code></td><td>2D</td><td>An image. Synonym: <code>billboard</code>.</td></tr>
* <tr><td><code>rectangle</code></td><td>2D</td><td>A rectangle.</td></tr>
* <tr><td><code>text</code></td><td>2D</td><td>Text.</td></tr>
* <tr><td><code>circle3d</code></td><td>3D</td><td>A circle.</td></tr>
* <tr><td><code>cube</code></td><td>3D</td><td>A cube. Can also use a <code>shape</code> overlay to create a
* cube.</td></tr>
* <tr><td><code>grid</code></td><td>3D</td><td>A grid of lines in a plane.</td></tr>
* <tr><td><code>image</code></td><td>2D</td><td>An image. Synonym: <code>billboard</code>.</td></tr>
* <tr><td><code>image3d</code></td><td>3D</td><td>An image.</td></tr>
* <tr><td><code>line3d</code></td><td>3D</td><td>A line.</td></tr>
* <tr><td><code>model</code></td><td>3D</td><td>A model.</td></tr>
* <tr><td><code>rectangle</code></td><td>2D</td><td>A rectangle.</td></tr>
* <tr><td><code>rectangle3d</code></td><td>3D</td><td>A rectangle.</td></tr>
* <tr><td><code>shape</code></td><td>3D</td><td>A geometric shape, such as a cube, sphere, or cylinder.</td></tr>
* <tr><td><code>sphere</code></td><td>3D</td><td>A sphere. Can also use a <code>shape</code> overlay to create a
* sphere.</td></tr>
* <tr><td><code>text</code></td><td>2D</td><td>Text.</td></tr>
* <tr><td><code>text3d</code></td><td>3D</td><td>Text.</td></tr>
* <tr><td><code>web3d</code></td><td>3D</td><td>Web content.</td></tr>
* </tbody>
* </table>
* <p>2D overlays are rendered on the display surface in desktop mode and on the HUD surface in HMD mode. 3D overlays are
* rendered at a position and orientation in-world.<p>
* rendered at a position and orientation in-world, but are deprecated (use local entities instead).<p>
* <p>Each overlay type has different {@link Overlays.OverlayProperties|OverlayProperties}.</p>
* @typedef {string} Overlays.OverlayType
*/
@ -203,18 +240,18 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
* <tr><th>{@link Overlays.OverlayType|OverlayType}</th><th>Overlay Properties</th></tr>
* </thead>
* <tbody>
* <tr><td><code>image</code></td><td>{@link Overlays.ImageProperties|ImageProperties}</td></tr>
* <tr><td><code>rectangle</code></td><td>{@link Overlays.RectangleProperties|RectangleProperties}</td></tr>
* <tr><td><code>text</code></td><td>{@link Overlays.TextProperties|TextProperties}</td></tr>
* <tr><td><code>circle3d</code></td><td>{@link Overlays.Circle3DProperties|Circle3DProperties}</td></tr>
* <tr><td><code>cube</code></td><td>{@link Overlays.CubeProperties|CubeProperties}</td></tr>
* <tr><td><code>grid</code></td><td>{@link Overlays.GridProperties|GridProperties}</td></tr>
* <tr><td><code>image</code></td><td>{@link Overlays.ImageProperties|ImageProperties}</td></tr>
* <tr><td><code>image3d</code></td><td>{@link Overlays.Image3DProperties|Image3DProperties}</td></tr>
* <tr><td><code>line3d</code></td><td>{@link Overlays.Line3DProperties|Line3DProperties}</td></tr>
* <tr><td><code>model</code></td><td>{@link Overlays.ModelProperties|ModelProperties}</td></tr>
* <tr><td><code>rectangle</code></td><td>{@link Overlays.RectangleProperties|RectangleProperties}</td></tr>
* <tr><td><code>rectangle3d</code></td><td>{@link Overlays.Rectangle3DProperties|Rectangle3DProperties}</td></tr>
* <tr><td><code>shape</code></td><td>{@link Overlays.ShapeProperties|ShapeProperties}</td></tr>
* <tr><td><code>sphere</code></td><td>{@link Overlays.SphereProperties|SphereProperties}</td></tr>
* <tr><td><code>text</code></td><td>{@link Overlays.TextProperties|TextProperties}</td></tr>
* <tr><td><code>text3d</code></td><td>{@link Overlays.Text3DProperties|Text3DProperties}</td></tr>
* <tr><td><code>web3d</code></td><td>{@link Overlays.Web3DProperties|Web3DProperties}</td></tr>
* </tbody>
@ -222,54 +259,42 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
* @typedef {object} Overlays.OverlayProperties
*/
Overlay::Pointer overlay;
if (type == ImageOverlay::TYPE) {
#if !defined(DISABLE_QML)
thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
overlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
#endif
} else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility
thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == TextOverlay::TYPE) {
#if !defined(DISABLE_QML)
thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
overlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
#endif
} else if (type == Text3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Shape3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Shape3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Cube3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Cube3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Sphere3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Sphere3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Circle3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Circle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Rectangle3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Rectangle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Line3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Line3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Grid3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Grid3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == ModelOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new ModelOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == Web3DOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new Web3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
} else if (type == RectangleOverlay::TYPE) {
thisOverlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
overlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
}
if (thisOverlay) {
thisOverlay->setProperties(properties.toMap());
return add2DOverlay(thisOverlay);
if (overlay) {
overlay->setProperties(properties.toMap());
return add2DOverlay(overlay);
}
return UNKNOWN_OVERLAY_ID;
QString entityType = overlayToEntityType(type);
if (entityType == "Unknown") {
return UNKNOWN_ENTITY_ID;
}
QVariantMap propertyMap = properties.toMap();
propertyMap["type"] = entityType;
return DependencyManager::get<EntityScriptingInterface>()->addEntity(convertOverlayToEntityProperties(propertyMap), "local");
}
QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
return UNKNOWN_ENTITY_ID;
}
QUuid thisID = QUuid::createUuid();
overlay->setOverlayID(thisID);
overlay->setID(thisID);
overlay->setStackOrder(_stackOrder++);
{
QMutexLocker locker(&_mutex);
@ -281,7 +306,7 @@ QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) {
QUuid Overlays::cloneOverlay(const QUuid& id) {
if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID;
return UNKNOWN_ENTITY_ID;
}
if (QThread::currentThread() != thread()) {
@ -486,111 +511,70 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray,
const QScriptValue& overlayIDsToInclude,
const QScriptValue& overlayIDsToDiscard,
bool visibleOnly, bool collidableOnly) {
const QVector<QUuid> overlaysToInclude = qVectorQUuidFromScriptValue(overlayIDsToInclude);
const QVector<QUuid> overlaysToDiscard = qVectorQUuidFromScriptValue(overlayIDsToDiscard);
const QVector<EntityItemID> include = qVectorEntityItemIDFromScriptValue(overlayIDsToInclude);
const QVector<EntityItemID> discard = qVectorEntityItemIDFromScriptValue(overlayIDsToDiscard);
return findRayIntersectionVector(ray, precisionPicking,
overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly);
return findRayIntersectionVector(ray, precisionPicking, include, discard, visibleOnly, collidableOnly);
}
RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking,
const QVector<QUuid>& overlaysToInclude,
const QVector<QUuid>& overlaysToDiscard,
const QVector<EntityItemID>& include,
const QVector<EntityItemID>& discard,
bool visibleOnly, bool collidableOnly) {
float bestDistance = std::numeric_limits<float>::max();
bool bestIsFront = false;
bool bestIsTablet = false;
auto tabletIDs = qApp->getTabletIDs();
unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES);
QMutexLocker locker(&_mutex);
RayToOverlayIntersectionResult result;
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
while (i.hasNext()) {
i.next();
OverlayID thisID = i.key();
auto thisOverlay = std::dynamic_pointer_cast<Base3DOverlay>(i.value());
if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) ||
(overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID))) {
continue;
if (!precisionPicking) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
}
if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) {
float thisDistance;
BoxFace thisFace;
glm::vec3 thisSurfaceNormal;
QVariantMap thisExtraInfo;
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance,
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
bool isDrawInFront = thisOverlay->getDrawInFront();
bool isTablet = tabletIDs.contains(thisID);
if ((isDrawInFront && !bestIsFront && !bestIsTablet)
|| ((isTablet || isDrawInFront || !bestIsFront) && thisDistance < bestDistance)) {
bestIsFront = isDrawInFront;
bestIsTablet = isTablet;
bestDistance = thisDistance;
result.intersects = true;
result.distance = thisDistance;
result.face = thisFace;
result.surfaceNormal = thisSurfaceNormal;
result.overlayID = thisID;
result.intersection = ray.origin + (ray.direction * thisDistance);
result.extraInfo = thisExtraInfo;
if (visibleOnly) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
}
if (collidableOnly) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
}
}
}
return result;
auto result = DependencyManager::get<EntityScriptingInterface>()->evalRayIntersectionVector(ray, PickFilter(searchFilter), include, discard);
RayToOverlayIntersectionResult overlayResult;
overlayResult.overlayID = result.entityID;
overlayResult.intersects = result.intersects;
overlayResult.intersection = result.intersection;
overlayResult.distance = result.distance;
overlayResult.surfaceNormal = result.surfaceNormal;
overlayResult.face = result.face;
overlayResult.extraInfo = result.extraInfo;
return overlayResult;
}
ParabolaToOverlayIntersectionResult Overlays::findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking,
const QVector<OverlayID>& overlaysToInclude,
const QVector<OverlayID>& overlaysToDiscard,
const QVector<EntityItemID>& include,
const QVector<EntityItemID>& discard,
bool visibleOnly, bool collidableOnly) {
float bestDistance = std::numeric_limits<float>::max();
bool bestIsFront = false;
const QVector<OverlayID> keyboardKeysToDiscard = DependencyManager::get<Keyboard>()->getKeysID();
QMutexLocker locker(&_mutex);
ParabolaToOverlayIntersectionResult result;
QMapIterator<OverlayID, Overlay::Pointer> i(_overlaysWorld);
while (i.hasNext()) {
i.next();
OverlayID thisID = i.key();
auto thisOverlay = std::dynamic_pointer_cast<Base3DOverlay>(i.value());
unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES);
if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) ||
(overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID)) ||
(keyboardKeysToDiscard.size() > 0 && keyboardKeysToDiscard.contains(thisID))) {
continue;
if (!precisionPicking) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
}
if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) {
float thisDistance;
BoxFace thisFace;
glm::vec3 thisSurfaceNormal;
QVariantMap thisExtraInfo;
if (thisOverlay->findParabolaIntersectionExtraInfo(parabola.origin, parabola.velocity, parabola.acceleration, thisDistance,
thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) {
bool isDrawInFront = thisOverlay->getDrawInFront();
if ((bestIsFront && isDrawInFront && thisDistance < bestDistance)
|| (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) {
if (visibleOnly) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
}
bestIsFront = isDrawInFront;
bestDistance = thisDistance;
result.intersects = true;
result.parabolicDistance = thisDistance;
result.face = thisFace;
result.surfaceNormal = thisSurfaceNormal;
result.overlayID = thisID;
result.intersection = parabola.origin + parabola.velocity * thisDistance + 0.5f * parabola.acceleration * thisDistance * thisDistance;
result.distance = glm::distance(result.intersection, parabola.origin);
result.extraInfo = thisExtraInfo;
if (collidableOnly) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
}
}
}
}
return result;
auto result = DependencyManager::get<EntityScriptingInterface>()->evalParabolaIntersectionVector(parabola, PickFilter(searchFilter), include, discard);
ParabolaToOverlayIntersectionResult overlayResult;
overlayResult.overlayID = result.entityID;
overlayResult.intersects = result.intersects;
overlayResult.intersection = result.intersection;
overlayResult.parabolicDistance = result.parabolicDistance;
overlayResult.surfaceNormal = result.surfaceNormal;
overlayResult.face = result.face;
overlayResult.extraInfo = result.extraInfo;
return overlayResult;
}
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
@ -671,28 +655,28 @@ bool Overlays::isAddedOverlay(const QUuid& id) {
return DependencyManager::get<EntityScriptingInterface>()->isAddedEntity(id);
}
void Overlays::sendMousePressOnOverlay(const QUuid& overlayID, const PointerEvent& event) {
mousePressPointerEvent(overlayID, event);
void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
mousePressPointerEvent(id, event);
}
void Overlays::sendMouseReleaseOnOverlay(const QUuid& overlayID, const PointerEvent& event) {
mouseReleasePointerEvent(overlayID, event);
void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
mouseReleasePointerEvent(id, event);
}
void Overlays::sendMouseMoveOnOverlay(const QUuid& overlayID, const PointerEvent& event) {
mouseMovePointerEvent(overlayID, event);
void Overlays::sendMouseMoveOnOverlay(const QUuid& id, const PointerEvent& event) {
mouseMovePointerEvent(id, event);
}
void Overlays::sendHoverEnterOverlay(const QUuid& overlayID, const PointerEvent& event) {
hoverEnterPointerEvent(overlayID, event);
void Overlays::sendHoverEnterOverlay(const QUuid& id, const PointerEvent& event) {
hoverEnterPointerEvent(id, event);
}
void Overlays::sendHoverOverOverlay(const QUuid& overlayID, const PointerEvent& event) {
hoverOverPointerEvent(overlayID, event);
void Overlays::sendHoverOverOverlay(const QUuid& id, const PointerEvent& event) {
hoverOverPointerEvent(id, event);
}
void Overlays::sendHoverLeaveOverlay(const QUuid& overlayID, const PointerEvent& event) {
hoverLeavePointerEvent(overlayID, event);
void Overlays::sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event) {
hoverLeavePointerEvent(id, event);
}
float Overlays::width() {
@ -719,28 +703,6 @@ float Overlays::height() {
return offscreenUi->getWindow()->size().height();
}
static glm::vec2 projectOntoOverlayXYPlane(glm::vec3 position, glm::quat rotation, glm::vec2 dimensions, const PickRay& pickRay,
const RayToOverlayIntersectionResult& rayPickResult) {
// Project the intersection point onto the local xy plane of the overlay.
float distance;
glm::vec3 planePosition = position;
glm::vec3 planeNormal = rotation * Vectors::UNIT_Z;
glm::vec3 overlayDimensions = glm::vec3(dimensions.x, dimensions.y, 0.0f);
glm::vec3 rayDirection = pickRay.direction;
glm::vec3 rayStart = pickRay.origin;
glm::vec3 p;
if (rayPlaneIntersection(planePosition, planeNormal, rayStart, rayDirection, distance)) {
p = rayStart + rayDirection * distance;
} else {
p = rayPickResult.intersection;
}
glm::vec3 localP = glm::inverse(rotation) * (p - position);
glm::vec3 normalizedP = (localP / overlayDimensions) + glm::vec3(0.5f);
return glm::vec2(normalizedP.x * overlayDimensions.x,
(1.0f - normalizedP.y) * overlayDimensions.y); // flip y-axis
}
static uint32_t toPointerButtons(const QMouseEvent& event) {
uint32_t buttons = 0;
buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 0;
@ -765,32 +727,18 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) {
PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray,
const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event,
PointerEvent::EventType eventType) {
auto overlay = std::dynamic_pointer_cast<Planar3DOverlay>(getOverlay(id));
if (getOverlayType(overlayID) == "web3d") {
overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (!overlay) {
return PointerEvent();
}
glm::vec3 position = overlay->getWorldPosition();
glm::quat rotation = overlay->getWorldOrientation();
glm::vec2 dimensions = overlay->getSize();
glm::vec2 pos2D = projectOntoOverlayXYPlane(position, rotation, dimensions, ray, rayPickResult);
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection);
PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal,
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers());
return pointerEvent;
}
bool Overlays::mousePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mousePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<QUuid>(), QVector<QUuid>());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID;
@ -799,35 +747,33 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
return true;
}
// if we didn't press on an overlay, disable overlay keyboard focus
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
setKeyboardFocusOverlay(UNKNOWN_ENTITY_ID);
// emit to scripts
emit mousePressOffOverlay();
return false;
}
void Overlays::mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
}
if (thisOverlay) {
void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any object to recieve events
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
if (event.shouldFocus()) {
// Focus keyboard on web overlays
DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
setKeyboardFocusOverlay(overlayID);
setKeyboardFocusOverlay(id);
}
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
web->handlePointerEvent(event);
}
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit mousePressOnOverlay(overlayID, event);
emit mousePressOnOverlay(id, event);
}
}
@ -835,7 +781,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(), QVector<OverlayID>());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID;
@ -849,60 +795,57 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
return false;
}
void Overlays::hoverEnterPointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any object to recieve events
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
web->hoverEnterEntity(event);
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "hoverEnterOverlay", Q_ARG(PointerEvent, event));
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit hoverEnterOverlay(overlayID, event);
emit hoverEnterOverlay(id, event);
}
}
void Overlays::hoverOverPointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
web->handlePointerEvent(event);
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit hoverOverOverlay(overlayID, event);
emit hoverOverOverlay(id, event);
}
}
void Overlays::hoverLeavePointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
web->hoverLeaveEntity(event);
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event));
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit hoverLeaveOverlay(overlayID, event);
emit hoverLeaveOverlay(id, event);
}
}
@ -910,33 +853,31 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
QVector<OverlayID>());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
}
_currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID;
_currentClickingOnOverlayID = UNKNOWN_ENTITY_ID;
return false;
}
void Overlays::mouseReleasePointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
web->handlePointerEvent(event);
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit mouseReleaseOnOverlay(overlayID, event);
emit mouseReleaseOnOverlay(id, event);
}
}
@ -944,14 +885,13 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(),
QVector<OverlayID>());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
// If previously hovering over a different overlay then leave hover on that overlay.
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
}
@ -967,33 +907,31 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
_currentHoverOverOverlayID = rayPickResult.overlayID;
} else {
// If previously hovering an overlay then leave hover.
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) {
if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID) {
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
_currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID;
_currentHoverOverOverlayID = UNKNOWN_ENTITY_ID;
}
}
return false;
}
void Overlays::mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event) {
void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay;
if (getOverlayType(overlayID) == "web3d") {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID));
auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (renderable) {
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
if (web) {
web->handlePointerEvent(event);
}
if (thisOverlay) {
// Send to web overlay
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
}
auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed
if (!keyboard->getKeysID().contains(overlayID)) {
if (!keyboard->getKeysID().contains(id)) {
// emit to scripts
emit mouseMoveOnOverlay(overlayID, event);
emit mouseMoveOnOverlay(id, event);
}
}

View file

@ -103,13 +103,13 @@ public:
QUuid add2DOverlay(const Overlay::Pointer& overlay);
RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking,
const QVector<QUuid>& overlaysToInclude,
const QVector<QUuid>& overlaysToDiscard,
const QVector<EntityItemID>& include,
const QVector<EntityItemID>& discard,
bool visibleOnly = false, bool collidableOnly = false);
ParabolaToOverlayIntersectionResult findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking,
const QVector<QUuid>& overlaysToInclude,
const QVector<QUuid>& overlaysToDiscard,
const QVector<EntityItemID>& include,
const QVector<EntityItemID>& discard,
bool visibleOnly = false, bool collidableOnly = false);
bool mousePressEvent(QMouseEvent* event);
@ -356,8 +356,8 @@ public slots:
* @function Overlays.findRayIntersection
* @param {PickRay} pickRay - The PickRay to use for finding overlays.
* @param {boolean} [precisionPicking=false] - <em>Unused</em>; exists to match Entity API.
* @param {Array.<Uuid>} [overlayIDsToInclude=[]] - If not empty then the search is restricted to these overlays.
* @param {Array.<Uuid>} [overlayIDsToExclude=[]] - Overlays to ignore during the search.
* @param {Array.<Uuid>} [include=[]] - If not empty then the search is restricted to these overlays.
* @param {Array.<Uuid>} [discard=[]] - Overlays to ignore during the search.
* @param {boolean} [visibleOnly=false] - <em>Unused</em>; exists to match Entity API.
* @param {boolean} [collidableOnly=false] - <em>Unused</em>; exists to match Entity API.
* @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by <code>pickRay</code>, taking
@ -379,8 +379,8 @@ public slots:
*/
RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray,
bool precisionPicking = false,
const QScriptValue& overlayIDsToInclude = QScriptValue(),
const QScriptValue& overlayIDsToDiscard = QScriptValue(),
const QScriptValue& include = QScriptValue(),
const QScriptValue& discard = QScriptValue(),
bool visibleOnly = false,
bool collidableOnly = false);
@ -718,6 +718,11 @@ private:
QUuid _currentClickingOnOverlayID;
QUuid _currentHoverOverOverlayID;
static QString entityToOverlayType(const QString& type);
static QString overlayToEntityType(const QString& type);
static std::unordered_map<QString, QString> _entityToOverlayTypes;
static std::unordered_map<QString, QString> _overlayToEntityTypes;
private slots:
void mousePressPointerEvent(const QUuid& id, const PointerEvent& event);
void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event);
@ -727,4 +732,8 @@ private slots:
void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event);
};
#define ADD_TYPE_MAP(entity, overlay) \
_entityToOverlayTypes[#entity] = #overlay; \
_overlayToEntityTypes[#overlay] = #entity;
#endif // hifi_Overlays_h

View file

@ -196,7 +196,7 @@ scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel() {
auto geometryCache = DependencyManager::get<GeometryCache>();
auto vertexColor = ColorUtils::toVec3(_color);
scriptable::ScriptableModelBase result;
result.objectID = getID();
result.objectID = Overlay::getID();
if (auto mesh = geometryCache->meshFromShape(_shape, vertexColor)) {
result.append(mesh);
}

View file

@ -128,7 +128,7 @@ scriptable::ScriptableModelBase Sphere3DOverlay::getScriptableModel() {
auto vertexColor = ColorUtils::toVec3(_color);
scriptable::ScriptableModelBase result;
if (auto mesh = geometryCache->meshFromShape(GeometryCache::Sphere, vertexColor)) {
result.objectID = getID();
result.objectID = Overlay::getID();
result.append(mesh);
}
return result;