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; EntityItemProperties properties;
properties.setType(EntityTypes::Web); properties.setType(EntityTypes::Web);
properties.setName("LoginDialogEntity"); properties.setName("LoginDialogEntity");
properties.setSourceUrl(LOGIN_DIALOG); properties.setSourceUrl(LOGIN_DIALOG.toString());
properties.setPosition(position); properties.setPosition(position);
properties.setRotation(cameraOrientation); properties.setRotation(cameraOrientation);
properties.setDimensions(LOGIN_DIMENSIONS); properties.setDimensions(LOGIN_DIMENSIONS);

View file

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

View file

@ -10,6 +10,8 @@
#include "PathPointer.h" #include "PathPointer.h"
#include <render/Item.h>
class ParabolaPointer : public PathPointer { class ParabolaPointer : public PathPointer {
using Parent = PathPointer; using Parent = PathPointer;
public: 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) { 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); return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized);
} }

View file

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

View file

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

View file

@ -27,15 +27,9 @@ public:
void setVisible(bool visible) override; void setVisible(bool visible) override;
bool queryAACubeNeedsUpdate() const override { return false; } // HACK: queryAACube not relevant for Overlays 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; virtual QString getName() const override;
void setName(QString name); void setName(QString name);
// getters
virtual bool is3D() const override { return true; }
virtual render::ItemKey getKey() override; virtual render::ItemKey getKey() override;
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); } 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(); } 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()); return ContextOverlayInterface::destroyContextOverlay(entityItemID, PointerEvent());
} }
void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
if (overlayID == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) { if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) {
qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "Overlay ID:" << overlayID; qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id;
emit contextOverlayClicked(_currentEntityWithContextOverlay); emit contextOverlayClicked(_currentEntityWithContextOverlay);
_contextOverlayJustClicked = true; _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) { 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; EntityItemProperties properties;
properties.setColor(CONTEXT_OVERLAY_COLOR); properties.setColor(CONTEXT_OVERLAY_COLOR);
properties.getPulse().setColorMode(PulseMode::NONE); 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) { 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; EntityItemProperties properties;
properties.setColor(CONTEXT_OVERLAY_COLOR); properties.setColor(CONTEXT_OVERLAY_COLOR);
properties.getPulse().setColorMode(PulseMode::IN_PHASE); 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()); bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get<PointerManager>()->isMouse(event.getID());
if (contextOverlayFilterPassed(entityID) && _enabled && !isMouse) { if (contextOverlayFilterPassed(id) && _enabled && !isMouse) {
enableEntityHighlight(entityID); 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()); bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get<PointerManager>()->isMouse(event.getID());
if (_currentEntityWithContextOverlay != entityID && _enabled && !isMouse) { if (_currentEntityWithContextOverlay != id && _enabled && !isMouse) {
disableEntityHighlight(entityID); disableEntityHighlight(id);
} }
} }
@ -388,12 +388,12 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID
} }
} }
void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityItemID) { void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityID) {
_selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID); _selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
} }
void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityItemID) { void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityID) {
_selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID); _selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
} }
void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) {

View file

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

View file

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

View file

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

View file

@ -70,9 +70,6 @@ public:
void setDrawHUDLayer(bool drawHUDLayer) override; void setDrawHUDLayer(bool drawHUDLayer) override;
void setGroupCulled(bool groupCulled); 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 scriptable::ScriptableModelBase getScriptableModel() override;
virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override; virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override;
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, 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 _isGroupCulled { false };
bool _groupCulledDirty { false }; bool _groupCulledDirty { false };
void processMaterials();
}; };
#endif // hifi_ModelOverlay_h #endif // hifi_ModelOverlay_h

View file

@ -24,8 +24,6 @@ public:
virtual AABox getBounds() const override; 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; } virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return 1; }
// getters // getters

View file

@ -21,20 +21,15 @@
#include "Application.h" #include "Application.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
#include "Image3DOverlay.h"
#include "Circle3DOverlay.h"
#include "Cube3DOverlay.h"
#include "Shape3DOverlay.h"
#include "ImageOverlay.h" #include "ImageOverlay.h"
#include "Line3DOverlay.h"
#include "ModelOverlay.h"
#include "Rectangle3DOverlay.h"
#include "Sphere3DOverlay.h"
#include "Grid3DOverlay.h"
#include "TextOverlay.h" #include "TextOverlay.h"
#include "RectangleOverlay.h" #include "RectangleOverlay.h"
#include "Text3DOverlay.h"
#include "Web3DOverlay.h" #include <raypick/RayPick.h>
#include <RenderableWebEntityItem.h>
#include "ui/Keyboard.h" #include "ui/Keyboard.h"
#include <QtQuick/QQuickWindow> #include <QtQuick/QQuickWindow>
@ -42,6 +37,9 @@
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") 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() { Overlays::Overlays() {
auto pointerManager = DependencyManager::get<PointerManager>(); auto pointerManager = DependencyManager::get<PointerManager>();
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent); 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::triggerBeginOverlay, this, &Overlays::mousePressPointerEvent);
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent); connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent);
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleasePointerEvent); 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() { void Overlays::cleanupAllOverlays() {
@ -151,9 +160,39 @@ Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const {
return nullptr; 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) { QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
if (_shuttingDown) { if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID; return UNKNOWN_ENTITY_ID;
} }
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
@ -163,8 +202,6 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
return result; return result;
} }
Overlay::Pointer thisOverlay = nullptr;
/**jsdoc /**jsdoc
* <p>An overlay may be one of the following types:</p> * <p>An overlay may be one of the following types:</p>
* <table> * <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> * <tr><th>Value</th><th>2D/3D</th><th>Description</th></tr>
* </thead> * </thead>
* <tbody> * <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>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 * <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> * 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>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>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>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>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>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>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 * <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> * 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>text3d</code></td><td>3D</td><td>Text.</td></tr>
* <tr><td><code>web3d</code></td><td>3D</td><td>Web content.</td></tr> * <tr><td><code>web3d</code></td><td>3D</td><td>Web content.</td></tr>
* </tbody> * </tbody>
* </table> * </table>
* <p>2D overlays are rendered on the display surface in desktop mode and on the HUD surface in HMD mode. 3D overlays are * <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> * <p>Each overlay type has different {@link Overlays.OverlayProperties|OverlayProperties}.</p>
* @typedef {string} Overlays.OverlayType * @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> * <tr><th>{@link Overlays.OverlayType|OverlayType}</th><th>Overlay Properties</th></tr>
* </thead> * </thead>
* <tbody> * <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>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>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>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>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>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>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>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>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>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>text3d</code></td><td>{@link Overlays.Text3DProperties|Text3DProperties}</td></tr>
* <tr><td><code>web3d</code></td><td>{@link Overlays.Web3DProperties|Web3DProperties}</td></tr> * <tr><td><code>web3d</code></td><td>{@link Overlays.Web3DProperties|Web3DProperties}</td></tr>
* </tbody> * </tbody>
@ -222,54 +259,42 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) {
* @typedef {object} Overlays.OverlayProperties * @typedef {object} Overlays.OverlayProperties
*/ */
Overlay::Pointer overlay;
if (type == ImageOverlay::TYPE) { if (type == ImageOverlay::TYPE) {
#if !defined(DISABLE_QML) #if !defined(DISABLE_QML)
thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); overlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
#endif #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) { } else if (type == TextOverlay::TYPE) {
#if !defined(DISABLE_QML) #if !defined(DISABLE_QML)
thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); overlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); });
#endif #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) { } 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) { if (overlay) {
thisOverlay->setProperties(properties.toMap()); overlay->setProperties(properties.toMap());
return add2DOverlay(thisOverlay); 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) { QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) {
if (_shuttingDown) { if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID; return UNKNOWN_ENTITY_ID;
} }
QUuid thisID = QUuid::createUuid(); QUuid thisID = QUuid::createUuid();
overlay->setOverlayID(thisID); overlay->setID(thisID);
overlay->setStackOrder(_stackOrder++); overlay->setStackOrder(_stackOrder++);
{ {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
@ -281,7 +306,7 @@ QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) {
QUuid Overlays::cloneOverlay(const QUuid& id) { QUuid Overlays::cloneOverlay(const QUuid& id) {
if (_shuttingDown) { if (_shuttingDown) {
return UNKNOWN_OVERLAY_ID; return UNKNOWN_ENTITY_ID;
} }
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
@ -486,111 +511,70 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray,
const QScriptValue& overlayIDsToInclude, const QScriptValue& overlayIDsToInclude,
const QScriptValue& overlayIDsToDiscard, const QScriptValue& overlayIDsToDiscard,
bool visibleOnly, bool collidableOnly) { bool visibleOnly, bool collidableOnly) {
const QVector<QUuid> overlaysToInclude = qVectorQUuidFromScriptValue(overlayIDsToInclude); const QVector<EntityItemID> include = qVectorEntityItemIDFromScriptValue(overlayIDsToInclude);
const QVector<QUuid> overlaysToDiscard = qVectorQUuidFromScriptValue(overlayIDsToDiscard); const QVector<EntityItemID> discard = qVectorEntityItemIDFromScriptValue(overlayIDsToDiscard);
return findRayIntersectionVector(ray, precisionPicking, return findRayIntersectionVector(ray, precisionPicking, include, discard, visibleOnly, collidableOnly);
overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly);
} }
RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking, RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking,
const QVector<QUuid>& overlaysToInclude, const QVector<EntityItemID>& include,
const QVector<QUuid>& overlaysToDiscard, const QVector<EntityItemID>& discard,
bool visibleOnly, bool collidableOnly) { bool visibleOnly, bool collidableOnly) {
float bestDistance = std::numeric_limits<float>::max(); unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES);
bool bestIsFront = false;
bool bestIsTablet = false;
auto tabletIDs = qApp->getTabletIDs();
QMutexLocker locker(&_mutex); if (!precisionPicking) {
RayToOverlayIntersectionResult result; searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
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 (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) { if (visibleOnly) {
float thisDistance; searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
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 (collidableOnly) {
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
} }
} auto result = DependencyManager::get<EntityScriptingInterface>()->evalRayIntersectionVector(ray, PickFilter(searchFilter), include, discard);
}
return result; 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, ParabolaToOverlayIntersectionResult Overlays::findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking,
const QVector<OverlayID>& overlaysToInclude, const QVector<EntityItemID>& include,
const QVector<OverlayID>& overlaysToDiscard, const QVector<EntityItemID>& discard,
bool visibleOnly, bool collidableOnly) { bool visibleOnly, bool collidableOnly) {
float bestDistance = std::numeric_limits<float>::max(); unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES);
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());
if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) || if (!precisionPicking) {
(overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID)) || searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
(keyboardKeysToDiscard.size() > 0 && keyboardKeysToDiscard.contains(thisID))) {
continue;
} }
if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) { if (visibleOnly) {
float thisDistance; searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
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))) {
bestIsFront = isDrawInFront; if (collidableOnly) {
bestDistance = thisDistance; searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
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;
} }
} auto result = DependencyManager::get<EntityScriptingInterface>()->evalParabolaIntersectionVector(parabola, PickFilter(searchFilter), include, discard);
}
} ParabolaToOverlayIntersectionResult overlayResult;
return result; 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) { QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
@ -671,28 +655,28 @@ bool Overlays::isAddedOverlay(const QUuid& id) {
return DependencyManager::get<EntityScriptingInterface>()->isAddedEntity(id); return DependencyManager::get<EntityScriptingInterface>()->isAddedEntity(id);
} }
void Overlays::sendMousePressOnOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) {
mousePressPointerEvent(overlayID, event); mousePressPointerEvent(id, event);
} }
void Overlays::sendMouseReleaseOnOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) {
mouseReleasePointerEvent(overlayID, event); mouseReleasePointerEvent(id, event);
} }
void Overlays::sendMouseMoveOnOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendMouseMoveOnOverlay(const QUuid& id, const PointerEvent& event) {
mouseMovePointerEvent(overlayID, event); mouseMovePointerEvent(id, event);
} }
void Overlays::sendHoverEnterOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendHoverEnterOverlay(const QUuid& id, const PointerEvent& event) {
hoverEnterPointerEvent(overlayID, event); hoverEnterPointerEvent(id, event);
} }
void Overlays::sendHoverOverOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendHoverOverOverlay(const QUuid& id, const PointerEvent& event) {
hoverOverPointerEvent(overlayID, event); hoverOverPointerEvent(id, event);
} }
void Overlays::sendHoverLeaveOverlay(const QUuid& overlayID, const PointerEvent& event) { void Overlays::sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event) {
hoverLeavePointerEvent(overlayID, event); hoverLeavePointerEvent(id, event);
} }
float Overlays::width() { float Overlays::width() {
@ -719,28 +703,6 @@ float Overlays::height() {
return offscreenUi->getWindow()->size().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) { static uint32_t toPointerButtons(const QMouseEvent& event) {
uint32_t buttons = 0; uint32_t buttons = 0;
buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 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, PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray,
const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event,
PointerEvent::EventType eventType) { PointerEvent::EventType eventType) {
auto overlay = std::dynamic_pointer_cast<Planar3DOverlay>(getOverlay(id)); glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection);
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);
PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal,
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers());
return pointerEvent; return pointerEvent;
} }
bool Overlays::mousePressEvent(QMouseEvent* event) { bool Overlays::mousePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mousePressEvent"); PerformanceTimer perfTimer("Overlays::mousePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); 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) { if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
@ -799,35 +747,33 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
return true; return true;
} }
// if we didn't press on an overlay, disable overlay keyboard focus // if we didn't press on an overlay, disable overlay keyboard focus
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); setKeyboardFocusOverlay(UNKNOWN_ENTITY_ID);
// emit to scripts // emit to scripts
emit mousePressOffOverlay(); emit mousePressOffOverlay();
return false; return false;
} }
void Overlays::mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events // TODO: generalize this to allow any object to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
} if (web) {
if (thisOverlay) {
if (event.shouldFocus()) { if (event.shouldFocus()) {
// Focus keyboard on web overlays // Focus keyboard on web overlays
DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
setKeyboardFocusOverlay(overlayID); setKeyboardFocusOverlay(id);
} }
// Send to web overlay web->handlePointerEvent(event);
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); }
} }
auto keyboard = DependencyManager::get<Keyboard>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 to scripts
emit mousePressOnOverlay(overlayID, event); emit mousePressOnOverlay(id, event);
} }
} }
@ -835,7 +781,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); 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) { if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
@ -849,60 +795,57 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
return false; return false;
} }
void Overlays::hoverEnterPointerEvent(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) {
// TODO: generalize this to allow any overlay to recieve events // TODO: generalize this to allow any object to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); 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>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 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 // TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); 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>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 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 // TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); 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>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 to scripts
emit hoverLeaveOverlay(overlayID, event); emit hoverLeaveOverlay(id, event);
} }
} }
@ -910,33 +853,31 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(), RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
QVector<OverlayID>());
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent); mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
} }
_currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID; _currentClickingOnOverlayID = UNKNOWN_ENTITY_ID;
return false; 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 // TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); 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>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 to scripts
emit mouseReleaseOnOverlay(overlayID, event); emit mouseReleaseOnOverlay(id, event);
} }
} }
@ -944,14 +885,13 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<OverlayID>(), RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector<EntityItemID>(), QVector<EntityItemID>());
QVector<OverlayID>());
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent); mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);
// If previously hovering over a different overlay then leave hover on that overlay. // 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); auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent); hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
} }
@ -967,33 +907,31 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
_currentHoverOverOverlayID = rayPickResult.overlayID; _currentHoverOverOverlayID = rayPickResult.overlayID;
} else { } else {
// If previously hovering an overlay then leave hover. // 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); auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent); hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent);
_currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID; _currentHoverOverOverlayID = UNKNOWN_ENTITY_ID;
} }
} }
return false; 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 // TODO: generalize this to allow any overlay to recieve events
std::shared_ptr<Web3DOverlay> thisOverlay; auto renderable = qApp->getEntities()->renderableForEntityId(id);
if (getOverlayType(overlayID) == "web3d") { if (renderable) {
thisOverlay = std::static_pointer_cast<Web3DOverlay>(getOverlay(overlayID)); 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>(); auto keyboard = DependencyManager::get<Keyboard>();
// Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed // 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 to scripts
emit mouseMoveOnOverlay(overlayID, event); emit mouseMoveOnOverlay(id, event);
} }
} }

View file

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

View file

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

View file

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