mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 20:16:16 +02:00
IT'S BUILDING (but still wip)
This commit is contained in:
parent
5ce8f566cc
commit
a2083d949e
17 changed files with 269 additions and 360 deletions
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "PathPointer.h"
|
||||
|
||||
#include <render/Item.h>
|
||||
|
||||
class ParabolaPointer : public PathPointer {
|
||||
using Parent = PathPointer;
|
||||
public:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() {
|
|||
tablet->gotoHomeScreen();
|
||||
hmd->closeTablet();
|
||||
}
|
||||
qApp->setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID);
|
||||
qApp->setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID);
|
||||
setAddressBarVisible(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -23,8 +23,6 @@ public:
|
|||
Overlay2D(const Overlay2D* overlay2D);
|
||||
|
||||
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; }
|
||||
|
||||
|
|
|
@ -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 (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 (!precisionPicking) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
|
||||
}
|
||||
return result;
|
||||
|
||||
if (visibleOnly) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
|
||||
}
|
||||
|
||||
if (collidableOnly) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
|
||||
}
|
||||
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 (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))) {
|
||||
|
||||
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 (!precisionPicking) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE);
|
||||
}
|
||||
return result;
|
||||
|
||||
if (visibleOnly) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE);
|
||||
}
|
||||
|
||||
if (collidableOnly) {
|
||||
searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE);
|
||||
}
|
||||
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) {
|
||||
if (event.shouldFocus()) {
|
||||
// Focus keyboard on web overlays
|
||||
DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||
setKeyboardFocusOverlay(overlayID);
|
||||
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(id);
|
||||
}
|
||||
|
||||
web->handlePointerEvent(event);
|
||||
}
|
||||
|
||||
// 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 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));
|
||||
}
|
||||
if (thisOverlay) {
|
||||
// Send to web overlay
|
||||
QMetaObject::invokeMethod(thisOverlay.get(), "hoverEnterOverlay", Q_ARG(PointerEvent, event));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
if (thisOverlay) {
|
||||
// Send to web overlay
|
||||
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||
auto renderable = qApp->getEntities()->renderableForEntityId(id);
|
||||
if (renderable) {
|
||||
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
|
||||
if (web) {
|
||||
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 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));
|
||||
}
|
||||
if (thisOverlay) {
|
||||
// Send to web overlay
|
||||
QMetaObject::invokeMethod(thisOverlay.get(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event));
|
||||
auto renderable = qApp->getEntities()->renderableForEntityId(id);
|
||||
if (renderable) {
|
||||
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
|
||||
if (web) {
|
||||
web->hoverLeaveEntity(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));
|
||||
}
|
||||
if (thisOverlay) {
|
||||
// Send to web overlay
|
||||
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||
auto renderable = qApp->getEntities()->renderableForEntityId(id);
|
||||
if (renderable) {
|
||||
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
|
||||
if (web) {
|
||||
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 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));
|
||||
}
|
||||
if (thisOverlay) {
|
||||
// Send to web overlay
|
||||
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||
auto renderable = qApp->getEntities()->renderableForEntityId(id);
|
||||
if (renderable) {
|
||||
auto web = std::dynamic_pointer_cast<render::entities::WebEntityRenderer>(renderable);
|
||||
if (web) {
|
||||
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 mouseMoveOnOverlay(overlayID, event);
|
||||
emit mouseMoveOnOverlay(id, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue