mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of git://github.com/highfidelity/hifi into shadow
This commit is contained in:
commit
dc8c75f403
31 changed files with 315 additions and 637 deletions
|
@ -22,8 +22,7 @@ RowLayout {
|
||||||
property var sample: null;
|
property var sample: null;
|
||||||
property bool isPlaying: false;
|
property bool isPlaying: false;
|
||||||
function createSampleSound() {
|
function createSampleSound() {
|
||||||
var SOUND = Qt.resolvedUrl("../../../sounds/sample.wav");
|
sound = ApplicationInterface.getSampleSound();
|
||||||
sound = SoundCache.getSound(SOUND);
|
|
||||||
sample = null;
|
sample = null;
|
||||||
}
|
}
|
||||||
function playSound() {
|
function playSound() {
|
||||||
|
|
Binary file not shown.
|
@ -692,7 +692,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<CloseEventSender>();
|
DependencyManager::set<CloseEventSender>();
|
||||||
DependencyManager::set<ResourceManager>();
|
DependencyManager::set<ResourceManager>();
|
||||||
DependencyManager::set<SelectionScriptingInterface>();
|
DependencyManager::set<SelectionScriptingInterface>();
|
||||||
DependencyManager::set<ContextOverlayInterface>();
|
|
||||||
DependencyManager::set<Ledger>();
|
DependencyManager::set<Ledger>();
|
||||||
DependencyManager::set<Wallet>();
|
DependencyManager::set<Wallet>();
|
||||||
DependencyManager::set<WalletScriptingInterface>();
|
DependencyManager::set<WalletScriptingInterface>();
|
||||||
|
@ -760,7 +759,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
_notifiedPacketVersionMismatchThisDomain(false),
|
_notifiedPacketVersionMismatchThisDomain(false),
|
||||||
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
|
||||||
_lastFaceTrackerUpdate(0),
|
_lastFaceTrackerUpdate(0),
|
||||||
_snapshotSound(nullptr)
|
_snapshotSound(nullptr),
|
||||||
|
_sampleSound(nullptr)
|
||||||
|
|
||||||
{
|
{
|
||||||
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
||||||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||||
|
@ -805,7 +806,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
installNativeEventFilter(&MyNativeEventFilter::getInstance());
|
installNativeEventFilter(&MyNativeEventFilter::getInstance());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
_logger = new FileLogger(this);
|
_logger = new FileLogger(this);
|
||||||
qInstallMessageHandler(messageHandler);
|
qInstallMessageHandler(messageHandler);
|
||||||
|
|
||||||
|
@ -982,6 +982,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
connect(myAvatar.get(), &MyAvatar::positionGoneTo,
|
connect(myAvatar.get(), &MyAvatar::positionGoneTo,
|
||||||
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
|
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
|
||||||
|
|
||||||
|
// Inititalize sample before registering
|
||||||
|
QFileInfo infSample = QFileInfo(PathUtils::resourcesPath() + "sounds/sample.wav");
|
||||||
|
_sampleSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(infSample.absoluteFilePath()));
|
||||||
|
|
||||||
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
||||||
scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){
|
scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){
|
||||||
registerScriptEngineWithApplicationServices(engine);
|
registerScriptEngineWithApplicationServices(engine);
|
||||||
|
@ -1183,7 +1187,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
// allow you to move an entity around in your hand
|
// allow you to move an entity around in your hand
|
||||||
_entityEditSender.setPacketsPerSecond(3000); // super high!!
|
_entityEditSender.setPacketsPerSecond(3000); // super high!!
|
||||||
|
|
||||||
|
// Overlays need to exist before we set the ContextOverlayInterface dependency
|
||||||
_overlays.init(); // do this before scripts load
|
_overlays.init(); // do this before scripts load
|
||||||
|
DependencyManager::set<ContextOverlayInterface>();
|
||||||
|
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
|
@ -1473,53 +1480,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the user clicks somewhere where there is NO entity at all, we will release focus
|
|
||||||
connect(getEntities().data(), &EntityTreeRenderer::mousePressOffEntity, [=]() {
|
|
||||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Keyboard focus handling for Web overlays.
|
// Keyboard focus handling for Web overlays.
|
||||||
auto overlays = &(qApp->getOverlays());
|
auto overlays = &(qApp->getOverlays());
|
||||||
|
|
||||||
connect(overlays, &Overlays::mousePressOnOverlay, [=](const OverlayID& overlayID, const PointerEvent& event) {
|
|
||||||
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays->getOverlay(overlayID));
|
|
||||||
// Only Web overlays can have keyboard focus.
|
|
||||||
if (thisOverlay) {
|
|
||||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
|
||||||
setKeyboardFocusOverlay(overlayID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
|
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
|
||||||
if (overlayID == _keyboardFocusedOverlay.get()) {
|
if (overlayID == _keyboardFocusedOverlay.get()) {
|
||||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(overlays, &Overlays::mousePressOffOverlay, [=]() {
|
|
||||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &Application::aboutToQuit, [=]() {
|
connect(this, &Application::aboutToQuit, [=]() {
|
||||||
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||||
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(overlays,
|
|
||||||
SIGNAL(mousePressOnOverlay(const OverlayID&, const PointerEvent&)),
|
|
||||||
DependencyManager::get<ContextOverlayInterface>().data(),
|
|
||||||
SLOT(contextOverlays_mousePressOnOverlay(const OverlayID&, const PointerEvent&)));
|
|
||||||
|
|
||||||
connect(overlays,
|
|
||||||
SIGNAL(hoverEnterOverlay(const OverlayID&, const PointerEvent&)),
|
|
||||||
DependencyManager::get<ContextOverlayInterface>().data(),
|
|
||||||
SLOT(contextOverlays_hoverEnterOverlay(const OverlayID&, const PointerEvent&)));
|
|
||||||
|
|
||||||
connect(overlays,
|
|
||||||
SIGNAL(hoverLeaveOverlay(const OverlayID&, const PointerEvent&)),
|
|
||||||
DependencyManager::get<ContextOverlayInterface>().data(),
|
|
||||||
SLOT(contextOverlays_hoverLeaveOverlay(const OverlayID&, const PointerEvent&)));
|
|
||||||
|
|
||||||
// Add periodic checks to send user activity data
|
// Add periodic checks to send user activity data
|
||||||
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
||||||
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
||||||
|
@ -1788,9 +1761,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
return entityServerNode && !isPhysicsEnabled();
|
return entityServerNode && !isPhysicsEnabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
|
QFileInfo infSnap = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
|
||||||
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(inf.absoluteFilePath()));
|
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(infSnap.absoluteFilePath()));
|
||||||
|
|
||||||
QVariant testProperty = property(hifi::properties::TEST);
|
QVariant testProperty = property(hifi::properties::TEST);
|
||||||
qDebug() << testProperty;
|
qDebug() << testProperty;
|
||||||
if (testProperty.isValid()) {
|
if (testProperty.isValid()) {
|
||||||
|
@ -4203,6 +4176,7 @@ void Application::initDisplay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::init() {
|
void Application::init() {
|
||||||
|
|
||||||
// Make sure Login state is up to date
|
// Make sure Login state is up to date
|
||||||
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
||||||
|
|
||||||
|
@ -4555,14 +4529,9 @@ QUuid Application::getKeyboardFocusEntity() const {
|
||||||
return _keyboardFocusedEntity.get();
|
return _keyboardFocusedEntity.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setKeyboardFocusEntity(QUuid id) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
setKeyboardFocusEntity(entityItemID);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
|
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
|
||||||
|
|
||||||
void Application::setKeyboardFocusEntity(EntityItemID entityItemID) {
|
void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
|
||||||
if (_keyboardFocusedEntity.get() != entityItemID) {
|
if (_keyboardFocusedEntity.get() != entityItemID) {
|
||||||
_keyboardFocusedEntity.set(entityItemID);
|
_keyboardFocusedEntity.set(entityItemID);
|
||||||
|
|
||||||
|
@ -4599,7 +4568,7 @@ OverlayID Application::getKeyboardFocusOverlay() {
|
||||||
return _keyboardFocusedOverlay.get();
|
return _keyboardFocusedOverlay.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setKeyboardFocusOverlay(OverlayID overlayID) {
|
void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
|
||||||
if (overlayID != _keyboardFocusedOverlay.get()) {
|
if (overlayID != _keyboardFocusedOverlay.get()) {
|
||||||
_keyboardFocusedOverlay.set(overlayID);
|
_keyboardFocusedOverlay.set(overlayID);
|
||||||
|
|
||||||
|
@ -6811,6 +6780,10 @@ void Application::loadScriptURLDialog() const {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedSoundPointer Application::getSampleSound() const {
|
||||||
|
return _sampleSound;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::loadLODToolsDialog() {
|
void Application::loadLODToolsDialog() {
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
|
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
|
||||||
|
@ -7433,51 +7406,6 @@ bool Application::isForeground() const {
|
||||||
return _isForeground && !_window->isMinimized();
|
return _isForeground && !_window->isMinimized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::sendMousePressOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->mousePressOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendMouseMoveOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->mouseMoveOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->mouseReleaseOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendClickDownOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->clickDownOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendHoldingClickOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->holdingClickOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendClickReleaseOnEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->clickReleaseOnEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendHoverEnterEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->hoverEnterEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendHoverOverEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->hoverOverEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::sendHoverLeaveEntity(QUuid id, PointerEvent event) {
|
|
||||||
EntityItemID entityItemID(id);
|
|
||||||
emit getEntities()->hoverLeaveEntity(entityItemID, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread?
|
// FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread?
|
||||||
static const int UI_RESERVED_THREADS = 1;
|
static const int UI_RESERVED_THREADS = 1;
|
||||||
// Windows won't let you have all the cores
|
// Windows won't let you have all the cores
|
||||||
|
|
|
@ -277,18 +277,6 @@ public:
|
||||||
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
|
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
|
||||||
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
|
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
|
||||||
|
|
||||||
Q_INVOKABLE void sendMousePressOnEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendMouseMoveOnEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendMouseReleaseOnEntity(QUuid id, PointerEvent event);
|
|
||||||
|
|
||||||
Q_INVOKABLE void sendClickDownOnEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendHoldingClickOnEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendClickReleaseOnEntity(QUuid id, PointerEvent event);
|
|
||||||
|
|
||||||
Q_INVOKABLE void sendHoverEnterEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendHoverOverEntity(QUuid id, PointerEvent event);
|
|
||||||
Q_INVOKABLE void sendHoverLeaveEntity(QUuid id, PointerEvent event);
|
|
||||||
|
|
||||||
OverlayID getTabletScreenID() const;
|
OverlayID getTabletScreenID() const;
|
||||||
OverlayID getTabletHomeButtonID() const;
|
OverlayID getTabletHomeButtonID() const;
|
||||||
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
QUuid getTabletFrameID() const; // may be an entity or an overlay
|
||||||
|
@ -326,6 +314,7 @@ public slots:
|
||||||
void toggleEntityScriptServerLogDialog();
|
void toggleEntityScriptServerLogDialog();
|
||||||
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
|
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
|
||||||
Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
|
Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
|
||||||
|
Q_INVOKABLE SharedSoundPointer getSampleSound() const;
|
||||||
|
|
||||||
void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const;
|
void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const;
|
||||||
|
|
||||||
|
@ -388,11 +377,10 @@ public slots:
|
||||||
void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions);
|
void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions);
|
||||||
|
|
||||||
QUuid getKeyboardFocusEntity() const; // thread-safe
|
QUuid getKeyboardFocusEntity() const; // thread-safe
|
||||||
void setKeyboardFocusEntity(QUuid id);
|
void setKeyboardFocusEntity(const EntityItemID& entityItemID);
|
||||||
void setKeyboardFocusEntity(EntityItemID entityItemID);
|
|
||||||
|
|
||||||
OverlayID getKeyboardFocusOverlay();
|
OverlayID getKeyboardFocusOverlay();
|
||||||
void setKeyboardFocusOverlay(OverlayID overlayID);
|
void setKeyboardFocusOverlay(const OverlayID& overlayID);
|
||||||
|
|
||||||
void addAssetToWorldMessageClose();
|
void addAssetToWorldMessageClose();
|
||||||
|
|
||||||
|
@ -702,6 +690,7 @@ private:
|
||||||
FileScriptingInterface* _fileDownload;
|
FileScriptingInterface* _fileDownload;
|
||||||
AudioInjectorPointer _snapshotSoundInjector;
|
AudioInjectorPointer _snapshotSoundInjector;
|
||||||
SharedSoundPointer _snapshotSound;
|
SharedSoundPointer _snapshotSound;
|
||||||
|
SharedSoundPointer _sampleSound;
|
||||||
|
|
||||||
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
|
DisplayPluginPointer _autoSwitchDisplayModeSupportedHMDPlugin;
|
||||||
QString _autoSwitchDisplayModeSupportedHMDPluginName;
|
QString _autoSwitchDisplayModeSupportedHMDPluginName;
|
||||||
|
|
|
@ -37,7 +37,7 @@ bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offse
|
||||||
// use the referencial from the avatar, y isn't always up
|
// use the referencial from the avatar, y isn't always up
|
||||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation()*Vectors::UP;
|
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getOrientation()*Vectors::UP;
|
||||||
|
|
||||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(billboardPos, cameraPos, avatarUP))));
|
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
|
||||||
|
|
||||||
transform.setRotation(rotation);
|
transform.setRotation(rotation);
|
||||||
transform.postRotate(offsetRotation);
|
transform.postRotate(offsetRotation);
|
||||||
|
|
|
@ -43,10 +43,10 @@ ContextOverlayInterface::ContextOverlayInterface() {
|
||||||
_entityPropertyFlags += PROP_REGISTRATION_POINT;
|
_entityPropertyFlags += PROP_REGISTRATION_POINT;
|
||||||
_entityPropertyFlags += PROP_CERTIFICATE_ID;
|
_entityPropertyFlags += PROP_CERTIFICATE_ID;
|
||||||
|
|
||||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>().data();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
||||||
connect(entityTreeRenderer, SIGNAL(mousePressOnEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(createOrDestroyContextOverlay(const EntityItemID&, const PointerEvent&)));
|
connect(entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity, this, &ContextOverlayInterface::createOrDestroyContextOverlay);
|
||||||
connect(entityTreeRenderer, SIGNAL(hoverEnterEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(contextOverlays_hoverEnterEntity(const EntityItemID&, const PointerEvent&)));
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity, this, &ContextOverlayInterface::contextOverlays_hoverEnterEntity);
|
||||||
connect(entityTreeRenderer, SIGNAL(hoverLeaveEntity(const EntityItemID&, const PointerEvent&)), this, SLOT(contextOverlays_hoverLeaveEntity(const EntityItemID&, const PointerEvent&)));
|
connect(entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity, this, &ContextOverlayInterface::contextOverlays_hoverLeaveEntity);
|
||||||
connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() {
|
connect(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"), &TabletProxy::tabletShownChanged, this, [&]() {
|
||||||
if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) {
|
if (_contextOverlayJustClicked && _hmdScriptingInterface->isMounted()) {
|
||||||
QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID();
|
QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID();
|
||||||
|
@ -59,9 +59,12 @@ ContextOverlayInterface::ContextOverlayInterface() {
|
||||||
_contextOverlayJustClicked = false;
|
_contextOverlayJustClicked = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>().data();
|
|
||||||
connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity);
|
connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity);
|
||||||
|
|
||||||
|
connect(&qApp->getOverlays(), &Overlays::mousePressOnOverlay, this, &ContextOverlayInterface::contextOverlays_mousePressOnOverlay);
|
||||||
|
connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
|
||||||
|
connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay);
|
||||||
|
|
||||||
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged);
|
connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -717,39 +717,34 @@ bool Overlays::isAddedOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "mousePressOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
mousePressEvent(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
void Overlays::sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "mouseReleaseOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
mouseReleaseEvent(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
void Overlays::sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "mouseMoveOnOverlay", Q_ARG(OverlayID, overlayID), Q_ARG(PointerEvent, event));
|
mouseMoveEvent(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverEnterOverlay(const OverlayID& id, const PointerEvent& event) {
|
void Overlays::sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "hoverEnterOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
emit hoverEnterOverlay(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverOverOverlay(const OverlayID& id, const PointerEvent& event) {
|
void Overlays::sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "hoverOverOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
emit hoverOverOverlay(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::sendHoverLeaveOverlay(const OverlayID& id, const PointerEvent& event) {
|
void Overlays::sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(this, "hoverLeaveOverlay", Q_ARG(OverlayID, id), Q_ARG(PointerEvent, event));
|
hoverLeaveEvent(overlayID, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayID Overlays::getKeyboardFocusOverlay() {
|
OverlayID Overlays::getKeyboardFocusOverlay() {
|
||||||
return qApp->getKeyboardFocusOverlay();
|
return qApp->getKeyboardFocusOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::setKeyboardFocusOverlay(OverlayID id) {
|
void Overlays::setKeyboardFocusOverlay(const OverlayID& id) {
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "setKeyboardFocusOverlay", Q_ARG(OverlayID, id));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qApp->setKeyboardFocusOverlay(id);
|
qApp->setKeyboardFocusOverlay(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,13 +879,35 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
||||||
emit mousePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
|
mousePressEvent(_currentClickingOnOverlayID, pointerEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// if we didn't press on an overlay, disable overlay keyboard focus
|
||||||
|
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
|
||||||
|
// emit to scripts
|
||||||
emit mousePressOffOverlay();
|
emit mousePressOffOverlay();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlays::mousePressEvent(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) {
|
||||||
|
// Focus keyboard on web overlays
|
||||||
|
DependencyManager::get<EntityScriptingInterface>()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||||
|
setKeyboardFocusOverlay(overlayID);
|
||||||
|
|
||||||
|
// Send to web overlay
|
||||||
|
QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit to scripts
|
||||||
|
emit mousePressOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
||||||
|
|
||||||
|
@ -900,13 +917,30 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||||
|
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press);
|
||||||
|
// emit to scripts
|
||||||
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
|
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// emit to scripts
|
||||||
emit mouseDoublePressOffOverlay();
|
emit mouseDoublePressOffOverlay();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlays::hoverLeaveEvent(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(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit to scripts
|
||||||
|
emit hoverLeaveOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
||||||
|
|
||||||
|
@ -914,13 +948,28 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
||||||
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);
|
||||||
emit mouseReleaseOnOverlay(rayPickResult.overlayID, pointerEvent);
|
mouseReleaseEvent(rayPickResult.overlayID, pointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID;
|
_currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlays::mouseReleaseEvent(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(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit to scripts
|
||||||
|
emit mouseReleaseOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
|
||||||
|
|
||||||
|
@ -928,12 +977,12 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
||||||
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);
|
||||||
emit mouseMoveOnOverlay(rayPickResult.overlayID, pointerEvent);
|
mouseMoveEvent(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_OVERLAY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
||||||
emit hoverLeaveOverlay(_currentHoverOverOverlayID, pointerEvent);
|
hoverLeaveEvent(_currentHoverOverOverlayID, pointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If hovering over a new overlay then enter hover on that overlay.
|
// If hovering over a new overlay then enter hover on that overlay.
|
||||||
|
@ -949,7 +998,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
// If previously hovering an overlay then leave hover.
|
// If previously hovering an overlay then leave hover.
|
||||||
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) {
|
if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) {
|
||||||
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move);
|
||||||
emit hoverLeaveOverlay(_currentHoverOverOverlayID, pointerEvent);
|
hoverLeaveEvent(_currentHoverOverOverlayID, pointerEvent);
|
||||||
|
|
||||||
_currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID;
|
_currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID;
|
||||||
}
|
}
|
||||||
|
@ -957,6 +1006,21 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlays::mouseMoveEvent(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(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit to scripts
|
||||||
|
emit mouseMoveOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
|
QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
|
||||||
QVector<QUuid> result;
|
QVector<QUuid> result;
|
||||||
//if (QThread::currentThread() != thread()) {
|
//if (QThread::currentThread() != thread()) {
|
||||||
|
|
|
@ -107,6 +107,11 @@ public:
|
||||||
bool mouseReleaseEvent(QMouseEvent* event);
|
bool mouseReleaseEvent(QMouseEvent* event);
|
||||||
bool mouseMoveEvent(QMouseEvent* event);
|
bool mouseMoveEvent(QMouseEvent* event);
|
||||||
|
|
||||||
|
void mousePressEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
void mouseMoveEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
void mouseReleaseEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
void hoverLeaveEvent(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
|
||||||
void cleanupAllOverlays();
|
void cleanupAllOverlays();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -298,12 +303,12 @@ public slots:
|
||||||
void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
|
||||||
void sendHoverEnterOverlay(const OverlayID& id, const PointerEvent& event);
|
void sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
void sendHoverOverOverlay(const OverlayID& id, const PointerEvent& event);
|
void sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
void sendHoverLeaveOverlay(const OverlayID& id, const PointerEvent& event);
|
void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event);
|
||||||
|
|
||||||
OverlayID getKeyboardFocusOverlay();
|
OverlayID getKeyboardFocusOverlay();
|
||||||
void setKeyboardFocusOverlay(OverlayID id);
|
void setKeyboardFocusOverlay(const OverlayID& id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -125,11 +125,7 @@ void Web3DOverlay::destroyWebSurface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_webSurface->pause();
|
_webSurface->pause();
|
||||||
auto overlays = &(qApp->getOverlays());
|
|
||||||
QObject::disconnect(overlays, &Overlays::mousePressOnOverlay, this, nullptr);
|
|
||||||
QObject::disconnect(overlays, &Overlays::mouseReleaseOnOverlay, this, nullptr);
|
|
||||||
QObject::disconnect(overlays, &Overlays::mouseMoveOnOverlay, this, nullptr);
|
|
||||||
QObject::disconnect(overlays, &Overlays::hoverLeaveOverlay, this, nullptr);
|
|
||||||
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
QObject::disconnect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||||
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
QObject::disconnect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, _webSurface);
|
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, _webSurface);
|
||||||
|
@ -160,35 +156,17 @@ void Web3DOverlay::buildWebSurface() {
|
||||||
_webSurface->resume();
|
_webSurface->resume();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto selfOverlayID = getOverlayID();
|
|
||||||
std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(qApp->getOverlays().getOverlay(selfOverlayID));
|
|
||||||
auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) {
|
|
||||||
auto self = weakSelf.lock();
|
|
||||||
if (self && overlayID == selfOverlayID) {
|
|
||||||
self->handlePointerEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto overlays = &(qApp->getOverlays());
|
|
||||||
QObject::connect(overlays, &Overlays::mousePressOnOverlay, this, forwardPointerEvent);
|
|
||||||
QObject::connect(overlays, &Overlays::mouseReleaseOnOverlay, this, forwardPointerEvent);
|
|
||||||
QObject::connect(overlays, &Overlays::mouseMoveOnOverlay, this, forwardPointerEvent);
|
|
||||||
QObject::connect(overlays, &Overlays::hoverLeaveOverlay, this, [=](OverlayID overlayID, const PointerEvent& event) {
|
|
||||||
auto self = weakSelf.lock();
|
|
||||||
if (!self) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (overlayID == selfOverlayID && (self->_pressed || (!self->_activeTouchPoints.empty() && self->_touchBeginAccepted))) {
|
|
||||||
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
|
||||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
|
||||||
forwardPointerEvent(overlayID, endEvent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||||
QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) {
|
||||||
|
if ((_pressed || (!_activeTouchPoints.empty() && _touchBeginAccepted))) {
|
||||||
|
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
||||||
|
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
||||||
|
handlePointerEvent(endEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Web3DOverlay::update(float deltatime) {
|
void Web3DOverlay::update(float deltatime) {
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
|
|
|
@ -39,7 +39,8 @@ public:
|
||||||
|
|
||||||
QObject* getEventHandler();
|
QObject* getEventHandler();
|
||||||
void setProxyWindow(QWindow* proxyWindow);
|
void setProxyWindow(QWindow* proxyWindow);
|
||||||
void handlePointerEvent(const PointerEvent& event);
|
Q_INVOKABLE void hoverLeaveOverlay(const PointerEvent& event);
|
||||||
|
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
|
||||||
void handlePointerEventAsTouch(const PointerEvent& event);
|
void handlePointerEventAsTouch(const PointerEvent& event);
|
||||||
void handlePointerEventAsMouse(const PointerEvent& event);
|
void handlePointerEventAsMouse(const PointerEvent& event);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ class SoundCache : public ResourceCache, public Dependency {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||||
const void* extra) override;
|
const void* extra) override;
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
|
#include "RenderableWebEntityItem.h"
|
||||||
|
|
||||||
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
|
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
|
||||||
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
|
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
|
||||||
|
|
||||||
|
@ -55,6 +57,32 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
EntityRenderer::initEntityRenderers();
|
EntityRenderer::initEntityRenderers();
|
||||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||||
|
|
||||||
|
// Forward mouse events to web entities
|
||||||
|
auto handlePointerEvent = [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||||
|
auto entity = getEntity(entityID);
|
||||||
|
if (entity && entity->getType() == EntityTypes::Web) {
|
||||||
|
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
|
||||||
|
}
|
||||||
|
if (thisEntity) {
|
||||||
|
QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent);
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent);
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent);
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
|
||||||
|
auto entity = getEntity(entityID);
|
||||||
|
if (entity && entity->getType() == EntityTypes::Web) {
|
||||||
|
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
|
||||||
|
}
|
||||||
|
if (thisEntity) {
|
||||||
|
QMetaObject::invokeMethod(thisEntity.get(), "hoverLeaveEntity", Q_ARG(PointerEvent, event));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTreeRenderer::~EntityTreeRenderer() {
|
EntityTreeRenderer::~EntityTreeRenderer() {
|
||||||
|
@ -78,13 +106,49 @@ render::ItemID EntityTreeRenderer::renderableIdForEntityId(const EntityItemID& i
|
||||||
int EntityTreeRenderer::_entitiesScriptEngineCount = 0;
|
int EntityTreeRenderer::_entitiesScriptEngineCount = 0;
|
||||||
|
|
||||||
void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
void EntityTreeRenderer::resetEntitiesScriptEngine() {
|
||||||
auto oldEngine = _entitiesScriptEngine;
|
|
||||||
_entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT,
|
_entitiesScriptEngine = scriptEngineFactory(ScriptEngine::ENTITY_CLIENT_SCRIPT, NO_SCRIPT,
|
||||||
QString("about:Entities %1").arg(++_entitiesScriptEngineCount));
|
QString("about:Entities %1").arg(++_entitiesScriptEngineCount));
|
||||||
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
_scriptingServices->registerScriptEngineWithApplicationServices(_entitiesScriptEngine);
|
||||||
_entitiesScriptEngine->runInThread();
|
_entitiesScriptEngine->runInThread();
|
||||||
auto entitiesScriptEngineProvider = qSharedPointerCast<EntitiesScriptEngineProvider>(_entitiesScriptEngine);
|
auto entitiesScriptEngineProvider = qSharedPointerCast<EntitiesScriptEngineProvider>(_entitiesScriptEngine);
|
||||||
DependencyManager::get<EntityScriptingInterface>()->setEntitiesScriptEngine(entitiesScriptEngineProvider);
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
|
entityScriptingInterface->setEntitiesScriptEngine(entitiesScriptEngineProvider);
|
||||||
|
|
||||||
|
// Connect mouse events to entity script callbacks
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mousePressOnEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseDoublePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseDoublePressOnEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveOnEntity", event);
|
||||||
|
// FIXME: this is a duplicate of mouseMoveOnEntity, but it seems like some scripts might use this naming
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveEvent", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseReleaseOnEntity", event);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "clickDownOnEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::holdingClickOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "holdingClickOnEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "clickReleaseOnEntity", event);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverEnterEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverOverEntity", event);
|
||||||
|
});
|
||||||
|
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) {
|
||||||
|
_entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverLeaveEntity", event);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::clear() {
|
void EntityTreeRenderer::clear() {
|
||||||
|
@ -264,8 +328,7 @@ void EntityTreeRenderer::update(bool simulate) {
|
||||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||||
// and we want to simulate this message here as well as in mouse move
|
// and we want to simulate this message here as well as in mouse move
|
||||||
if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) {
|
if (_lastPointerEventValid && !_currentClickingOnEntityID.isInvalidID()) {
|
||||||
emit holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent);
|
emit DependencyManager::get<EntityScriptingInterface>()->holdingClickOnEntity(_currentClickingOnEntityID, _lastPointerEvent);
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", _lastPointerEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,19 +498,6 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::clickDownOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::holdingClickOnEntity, entityScriptingInterface, &EntityScriptingInterface::holdingClickOnEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::clickReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickReleaseOnEntity);
|
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
|
||||||
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
|
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
|
||||||
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
|
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
|
||||||
connect(this, &EntityTreeRenderer::collisionWithEntity, entityScriptingInterface, &EntityScriptingInterface::collisionWithEntity);
|
connect(this, &EntityTreeRenderer::collisionWithEntity, entityScriptingInterface, &EntityScriptingInterface::collisionWithEntity);
|
||||||
|
@ -516,13 +566,11 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects && rayPickResult.entity) {
|
||||||
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
|
auto properties = rayPickResult.entity->getProperties();
|
||||||
|
|
||||||
auto entity = getTree()->findEntityByEntityItemID(rayPickResult.entityID);
|
|
||||||
auto properties = entity->getProperties();
|
|
||||||
QString urlString = properties.getHref();
|
QString urlString = properties.getHref();
|
||||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||||
if (url.isValid() && !url.isEmpty()){
|
if (url.isValid() && !url.isEmpty()){
|
||||||
|
@ -536,23 +584,16 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit mousePressOnEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->mousePressOnEntity(rayPickResult.entityID, pointerEvent);
|
||||||
|
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mousePressOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||||
emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
|
emit entityScriptingInterface->clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "clickDownOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastPointerEvent = pointerEvent;
|
_lastPointerEvent = pointerEvent;
|
||||||
_lastPointerEventValid = true;
|
_lastPointerEventValid = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
emit mousePressOffEntity();
|
emit entityScriptingInterface->mousePressOffEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,34 +605,25 @@ void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects && rayPickResult.entity) {
|
||||||
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
|
|
||||||
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
rayPickResult.surfaceNormal, ray.direction,
|
rayPickResult.surfaceNormal, ray.direction,
|
||||||
toPointerButton(*event), toPointerButtons(*event), Qt::NoModifier);
|
toPointerButton(*event), toPointerButtons(*event), Qt::NoModifier);
|
||||||
|
|
||||||
emit mouseDoublePressOnEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->mouseDoublePressOnEntity(rayPickResult.entityID, pointerEvent);
|
||||||
|
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseDoublePressOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||||
emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
|
emit entityScriptingInterface->clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "doubleclickOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastPointerEvent = pointerEvent;
|
_lastPointerEvent = pointerEvent;
|
||||||
_lastPointerEventValid = true;
|
_lastPointerEventValid = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
emit mouseDoublePressOffEntity();
|
emit entityScriptingInterface->mouseDoublePressOffEntity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,9 +635,10 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects && rayPickResult.entity) {
|
||||||
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
//qCDebug(entitiesrenderer) << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||||
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
|
@ -615,31 +648,23 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseReleaseOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastPointerEvent = pointerEvent;
|
_lastPointerEvent = pointerEvent;
|
||||||
_lastPointerEventValid = true;
|
_lastPointerEventValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now
|
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now
|
||||||
// we're releasing the button, then this is considered a clickOn event
|
// we're releasing the button, then this is considered a clickReleaseOn event
|
||||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||||
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
auto entity = getTree()->findEntityByID(_currentClickingOnEntityID);
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
|
||||||
PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
rayPickResult.surfaceNormal, ray.direction,
|
rayPickResult.surfaceNormal, ray.direction,
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent);
|
emit entityScriptingInterface->clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "clickReleaseOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// makes it the unknown ID, we just released so we can't be clicking on anything
|
// makes it the unknown ID, we just released so we can't be clicking on anything
|
||||||
|
@ -654,9 +679,10 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||||
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||||
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
RayToEntityIntersectionResult rayPickResult = _getPrevRayPickResultOperator(_mouseRayPickID);
|
||||||
if (rayPickResult.intersects) {
|
if (rayPickResult.intersects && rayPickResult.entity) {
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
|
@ -664,48 +690,32 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit mouseMoveOnEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->mouseMoveOnEntity(rayPickResult.entityID, pointerEvent);
|
||||||
|
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveEvent", pointerEvent);
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseMoveOnEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle the hover logic...
|
// handle the hover logic...
|
||||||
|
|
||||||
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity
|
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity
|
||||||
// then we need to send the hover leave.
|
// then we need to send the hover leave.
|
||||||
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
|
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||||
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
auto entity = getTree()->findEntityByID(_currentHoverOverEntityID);
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
|
||||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
rayPickResult.surfaceNormal, ray.direction,
|
rayPickResult.surfaceNormal, ray.direction,
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
emit entityScriptingInterface->hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the new hover entity does not match the previous hover entity then we are entering the new one
|
// If the new hover entity does not match the previous hover entity then we are entering the new one
|
||||||
// this is true if the _currentHoverOverEntityID is known or unknown
|
// this is true if the _currentHoverOverEntityID is known or unknown
|
||||||
if (rayPickResult.entityID != _currentHoverOverEntityID) {
|
if (rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||||
emit hoverEnterEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->hoverEnterEntity(rayPickResult.entityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverEnterEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
|
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
|
||||||
// we should send our hover over event
|
// we should send our hover over event
|
||||||
emit hoverOverEntity(rayPickResult.entityID, pointerEvent);
|
emit entityScriptingInterface->hoverOverEntity(rayPickResult.entityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "hoverOverEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember what we're hovering over
|
// remember what we're hovering over
|
||||||
_currentHoverOverEntityID = rayPickResult.entityID;
|
_currentHoverOverEntityID = rayPickResult.entityID;
|
||||||
|
@ -718,38 +728,18 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
|
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
|
||||||
// send the hover leave for our previous entity
|
// send the hover leave for our previous entity
|
||||||
if (!_currentHoverOverEntityID.isInvalidID()) {
|
if (!_currentHoverOverEntityID.isInvalidID()) {
|
||||||
|
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||||
auto entity = getTree()->findEntityByID(_currentHoverOverEntityID);
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
|
||||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||||
pos2D, rayPickResult.intersection,
|
pos2D, rayPickResult.intersection,
|
||||||
rayPickResult.surfaceNormal, ray.direction,
|
rayPickResult.surfaceNormal, ray.direction,
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
toPointerButton(*event), toPointerButtons(*event),
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||||
|
|
||||||
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
emit entityScriptingInterface->hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentHoverOverEntityID, "hoverLeaveEntity", pointerEvent);
|
|
||||||
}
|
|
||||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID
|
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have
|
_lastPointerEvent = pointerEvent;
|
||||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
_lastPointerEventValid = true;
|
||||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
|
||||||
|
|
||||||
auto entity = getTree()->findEntityByID(_currentClickingOnEntityID);
|
|
||||||
glm::vec2 pos2D = projectOntoEntityXYPlane(entity, ray, rayPickResult);
|
|
||||||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
|
||||||
pos2D, rayPickResult.intersection,
|
|
||||||
rayPickResult.surfaceNormal, ray.direction,
|
|
||||||
toPointerButton(*event), toPointerButtons(*event),
|
|
||||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
|
||||||
|
|
||||||
emit holdingClickOnEntity(_currentClickingOnEntityID, pointerEvent);
|
|
||||||
if (_entitiesScriptEngine) {
|
|
||||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "holdingClickOnEntity", pointerEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,21 +117,6 @@ public:
|
||||||
void onEntityChanged(const EntityItemID& id);
|
void onEntityChanged(const EntityItemID& id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void mousePressOffEntity();
|
|
||||||
void mouseDoublePressOffEntity();
|
|
||||||
|
|
||||||
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void clickReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
|
|
||||||
void hoverEnterEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void hoverOverEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
void hoverLeaveEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
|
||||||
|
|
||||||
void enterEntity(const EntityItemID& entityItemID);
|
void enterEntity(const EntityItemID& entityItemID);
|
||||||
void leaveEntity(const EntityItemID& entityItemID);
|
void leaveEntity(const EntityItemID& entityItemID);
|
||||||
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include <ui/TabletScriptingInterface.h>
|
#include <ui/TabletScriptingInterface.h>
|
||||||
#include <EntityScriptingInterface.h>
|
#include <EntityScriptingInterface.h>
|
||||||
|
|
||||||
#include "EntityTreeRenderer.h"
|
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +85,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_lastLocked != entity->getLocked()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +139,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastDPI = entity->getDPI();
|
_lastDPI = entity->getDPI();
|
||||||
|
_lastLocked = entity->getLocked();
|
||||||
|
|
||||||
glm::vec2 windowSize = getWindowSize(entity);
|
glm::vec2 windowSize = getWindowSize(entity);
|
||||||
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||||
|
@ -234,38 +238,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
emit entities->webEventReceived(entityItemID, message);
|
emit entities->webEventReceived(entityItemID, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) {
|
|
||||||
if (entityItemID == entity->getID()) {
|
|
||||||
handlePointerEvent(entity, event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto renderer = DependencyManager::get<EntityTreeRenderer>();
|
|
||||||
QObject::connect(renderer.data(), &EntityTreeRenderer::mousePressOnEntity, this, forwardPointerEvent);
|
|
||||||
QObject::connect(renderer.data(), &EntityTreeRenderer::mouseReleaseOnEntity, this, forwardPointerEvent);
|
|
||||||
QObject::connect(renderer.data(), &EntityTreeRenderer::mouseMoveOnEntity, this, forwardPointerEvent);
|
|
||||||
QObject::connect(renderer.data(), &EntityTreeRenderer::hoverLeaveEntity, this,
|
|
||||||
[=](const EntityItemID& entityItemID, const PointerEvent& event) {
|
|
||||||
if (this->_pressed && entity->getID() == entityItemID) {
|
|
||||||
// If the user mouses off the entity while the button is down, simulate a touch end.
|
|
||||||
QTouchEvent::TouchPoint point;
|
|
||||||
point.setId(event.getID());
|
|
||||||
point.setState(Qt::TouchPointReleased);
|
|
||||||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
|
|
||||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
|
||||||
point.setScenePos(windowPoint);
|
|
||||||
point.setPos(windowPoint);
|
|
||||||
QList<QTouchEvent::TouchPoint> touchPoints;
|
|
||||||
touchPoints.push_back(point);
|
|
||||||
QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr,
|
|
||||||
Qt::NoModifier, Qt::TouchPointReleased, touchPoints);
|
|
||||||
touchEvent->setWindow(_webSurface->getWindow());
|
|
||||||
touchEvent->setDevice(&_touchDevice);
|
|
||||||
touchEvent->setTarget(_webSurface->getRootItem());
|
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,13 +267,6 @@ void WebEntityRenderer::destroyWebSurface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
webSurface->pause();
|
webSurface->pause();
|
||||||
auto renderer = DependencyManager::get<EntityTreeRenderer>();
|
|
||||||
if (renderer) {
|
|
||||||
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mousePressOnEntity, this, nullptr);
|
|
||||||
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mouseReleaseOnEntity, this, nullptr);
|
|
||||||
QObject::disconnect(renderer.data(), &EntityTreeRenderer::mouseMoveOnEntity, this, nullptr);
|
|
||||||
QObject::disconnect(renderer.data(), &EntityTreeRenderer::hoverLeaveEntity, this, nullptr);
|
|
||||||
}
|
|
||||||
webSurface.reset();
|
webSurface.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,13 +312,34 @@ void WebEntityRenderer::loadSourceURL() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) {
|
void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) {
|
||||||
|
if (!_lastLocked && _webSurface && _pressed) {
|
||||||
|
// If the user mouses off the entity while the button is down, simulate a touch end.
|
||||||
|
QTouchEvent::TouchPoint point;
|
||||||
|
point.setId(event.getID());
|
||||||
|
point.setState(Qt::TouchPointReleased);
|
||||||
|
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
|
||||||
|
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||||
|
point.setScenePos(windowPoint);
|
||||||
|
point.setPos(windowPoint);
|
||||||
|
QList<QTouchEvent::TouchPoint> touchPoints;
|
||||||
|
touchPoints.push_back(point);
|
||||||
|
QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr,
|
||||||
|
Qt::NoModifier, Qt::TouchPointReleased, touchPoints);
|
||||||
|
touchEvent->setWindow(_webSurface->getWindow());
|
||||||
|
touchEvent->setDevice(&_touchDevice);
|
||||||
|
touchEvent->setTarget(_webSurface->getRootItem());
|
||||||
|
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) {
|
||||||
// Ignore mouse interaction if we're locked
|
// Ignore mouse interaction if we're locked
|
||||||
if (entity->getLocked() || !_webSurface) {
|
if (_lastLocked || !_webSurface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * entity->getDPI());
|
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _lastDPI);
|
||||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||||
if (event.getType() == PointerEvent::Move) {
|
if (event.getType() == PointerEvent::Move) {
|
||||||
// Forward a mouse move event to webSurface
|
// Forward a mouse move event to webSurface
|
||||||
|
|
|
@ -18,12 +18,16 @@ class PointerEvent;
|
||||||
namespace render { namespace entities {
|
namespace render { namespace entities {
|
||||||
|
|
||||||
class WebEntityRenderer : public TypedEntityRenderer<WebEntityItem> {
|
class WebEntityRenderer : public TypedEntityRenderer<WebEntityItem> {
|
||||||
|
Q_OBJECT
|
||||||
using Parent = TypedEntityRenderer<WebEntityItem>;
|
using Parent = TypedEntityRenderer<WebEntityItem>;
|
||||||
friend class EntityRenderer;
|
friend class EntityRenderer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebEntityRenderer(const EntityItemPointer& entity);
|
WebEntityRenderer(const EntityItemPointer& entity);
|
||||||
|
|
||||||
|
Q_INVOKABLE void hoverLeaveEntity(const PointerEvent& event);
|
||||||
|
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||||
virtual bool needsRenderUpdate() const override;
|
virtual bool needsRenderUpdate() const override;
|
||||||
|
@ -44,9 +48,6 @@ private:
|
||||||
bool hasWebSurface();
|
bool hasWebSurface();
|
||||||
void loadSourceURL();
|
void loadSourceURL();
|
||||||
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
||||||
void handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int _geometryId{ 0 };
|
int _geometryId{ 0 };
|
||||||
enum contentType {
|
enum contentType {
|
||||||
|
@ -60,6 +61,7 @@ private:
|
||||||
bool _pressed{ false };
|
bool _pressed{ false };
|
||||||
QString _lastSourceUrl;
|
QString _lastSourceUrl;
|
||||||
uint16_t _lastDPI;
|
uint16_t _lastDPI;
|
||||||
|
bool _lastLocked;
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
uint64_t _lastRenderTime { 0 };
|
uint64_t _lastRenderTime { 0 };
|
||||||
Transform _renderTransform;
|
Transform _renderTransform;
|
||||||
|
|
|
@ -51,6 +51,10 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership
|
||||||
connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged);
|
connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged);
|
||||||
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged);
|
||||||
|
|
||||||
|
// If the user clicks somewhere where there is no entity at all, we will release focus
|
||||||
|
connect(this, &EntityScriptingInterface::mousePressOffEntity, [=]() {
|
||||||
|
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
|
||||||
|
});
|
||||||
|
|
||||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
||||||
|
@ -1674,44 +1678,44 @@ QUuid EntityScriptingInterface::getKeyboardFocusEntity() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::setKeyboardFocusEntity(QUuid id) {
|
void EntityScriptingInterface::setKeyboardFocusEntity(const EntityItemID& id) {
|
||||||
QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::QueuedConnection, Q_ARG(QUuid, id));
|
QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendMousePressOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendMousePressOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit mousePressOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendMouseMoveOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendMouseMoveOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendMouseMoveOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit mouseMoveOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendMouseReleaseOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendMouseReleaseOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit mouseReleaseOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendClickDownOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendClickDownOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendClickDownOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit clickDownOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendHoldingClickOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendHoldingClickOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendHoldingClickOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit holdingClickOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendClickReleaseOnEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendClickReleaseOnEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendClickReleaseOnEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit clickReleaseOnEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendHoverEnterEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendHoverEnterEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendHoverEnterEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit hoverEnterEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendHoverOverEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendHoverOverEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendHoverOverEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit hoverOverEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::sendHoverLeaveEntity(QUuid id, PointerEvent event) {
|
void EntityScriptingInterface::sendHoverLeaveEntity(const EntityItemID& id, const PointerEvent& event) {
|
||||||
QMetaObject::invokeMethod(qApp, "sendHoverLeaveEntity", Qt::QueuedConnection, Q_ARG(QUuid, id), Q_ARG(PointerEvent, event));
|
emit hoverLeaveEntity(id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) {
|
bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) {
|
||||||
|
|
|
@ -380,19 +380,19 @@ public slots:
|
||||||
Q_INVOKABLE QString getNestableType(QUuid id);
|
Q_INVOKABLE QString getNestableType(QUuid id);
|
||||||
|
|
||||||
Q_INVOKABLE QUuid getKeyboardFocusEntity() const;
|
Q_INVOKABLE QUuid getKeyboardFocusEntity() const;
|
||||||
Q_INVOKABLE void setKeyboardFocusEntity(QUuid id);
|
Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& id);
|
||||||
|
|
||||||
Q_INVOKABLE void sendMousePressOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendMouseMoveOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendMouseMoveOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendMouseReleaseOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendMouseReleaseOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
|
|
||||||
Q_INVOKABLE void sendClickDownOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendClickDownOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendHoldingClickOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendHoldingClickOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendClickReleaseOnEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendClickReleaseOnEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
|
|
||||||
Q_INVOKABLE void sendHoverEnterEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendHoverEnterEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendHoverOverEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendHoverOverEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
Q_INVOKABLE void sendHoverLeaveEntity(QUuid id, PointerEvent event);
|
Q_INVOKABLE void sendHoverLeaveEntity(const EntityItemID& id, const PointerEvent& event);
|
||||||
|
|
||||||
Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id);
|
Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id);
|
||||||
|
|
||||||
|
@ -439,8 +439,11 @@ signals:
|
||||||
void canWriteAssetsChanged(bool canWriteAssets);
|
void canWriteAssetsChanged(bool canWriteAssets);
|
||||||
|
|
||||||
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
|
void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
|
void mousePressOffEntity();
|
||||||
|
void mouseDoublePressOffEntity();
|
||||||
|
|
||||||
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
|
|
|
@ -511,12 +511,19 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
|
|
||||||
auto keyLight = lightAndShadow.first;
|
auto keyLight = lightAndShadow.first;
|
||||||
|
|
||||||
|
model::LightPointer keyAmbientLight;
|
||||||
|
if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
|
||||||
|
keyAmbientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front());
|
||||||
|
}
|
||||||
|
bool hasAmbientMap = (keyAmbientLight != nullptr);
|
||||||
|
|
||||||
// Setup the global directional pass pipeline
|
// Setup the global directional pass pipeline
|
||||||
{
|
{
|
||||||
if (deferredLightingEffect->_shadowMapEnabled) {
|
if (deferredLightingEffect->_shadowMapEnabled) {
|
||||||
|
|
||||||
// If the keylight has an ambient Map then use the Skybox version of the pass
|
// If the keylight has an ambient Map then use the Skybox version of the pass
|
||||||
// otherwise use the ambient sphere version
|
// otherwise use the ambient sphere version
|
||||||
if (keyLight->getAmbientMap()) {
|
if (hasAmbientMap) {
|
||||||
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
program = deferredLightingEffect->_directionalSkyboxLightShadow;
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
|
locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations;
|
||||||
} else {
|
} else {
|
||||||
|
@ -526,7 +533,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
} else {
|
} else {
|
||||||
// If the keylight has an ambient Map then use the Skybox version of the pass
|
// If the keylight has an ambient Map then use the Skybox version of the pass
|
||||||
// otherwise use the ambient sphere version
|
// otherwise use the ambient sphere version
|
||||||
if (keyLight->getAmbientMap()) {
|
if (hasAmbientMap) {
|
||||||
program = deferredLightingEffect->_directionalSkyboxLight;
|
program = deferredLightingEffect->_directionalSkyboxLight;
|
||||||
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -138,7 +138,7 @@ void main(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mix with background at far range
|
// Mix with background at far range
|
||||||
const float BLEND_DISTANCE = 30000.0;
|
const float BLEND_DISTANCE = 27000.0;
|
||||||
if (distance > BLEND_DISTANCE) {
|
if (distance > BLEND_DISTANCE) {
|
||||||
outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue);
|
outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -97,7 +97,6 @@ static const bool HIFI_AUTOREFRESH_FILE_SCRIPTS { true };
|
||||||
Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature)
|
Q_DECLARE_METATYPE(QScriptEngine::FunctionSignature)
|
||||||
int functionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>();
|
int functionSignatureMetaID = qRegisterMetaType<QScriptEngine::FunctionSignature>();
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ScriptEnginePointer)
|
|
||||||
int scriptEnginePointerMetaID = qRegisterMetaType<ScriptEnginePointer>();
|
int scriptEnginePointerMetaID = qRegisterMetaType<ScriptEnginePointer>();
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(scriptengineScript, "hifi.scriptengine.script")
|
Q_LOGGING_CATEGORY(scriptengineScript, "hifi.scriptengine.script")
|
||||||
|
|
|
@ -55,6 +55,8 @@ static const int DEFAULT_ENTITY_PPS_PER_SCRIPT = 900;
|
||||||
|
|
||||||
class ScriptEngines;
|
class ScriptEngines;
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ScriptEnginePointer)
|
||||||
|
|
||||||
class CallbackData {
|
class CallbackData {
|
||||||
public:
|
public:
|
||||||
QScriptValue function;
|
QScriptValue function;
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,89 +0,0 @@
|
||||||
//
|
|
||||||
// spawnStopwatch.js
|
|
||||||
//
|
|
||||||
// Created by Ryan Huffman on 1/20/17.
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
var forward = Quat.getFront(MyAvatar.orientation);
|
|
||||||
Vec3.print("Forward: ", forward);
|
|
||||||
var positionToSpawn = Vec3.sum(MyAvatar.position, Vec3.multiply(3, forward));
|
|
||||||
var scale = 0.5;
|
|
||||||
positionToSpawn.y += 0.5;
|
|
||||||
|
|
||||||
var stopwatchID = Entities.addEntity({
|
|
||||||
type: "Model",
|
|
||||||
name: "stopwatch/base",
|
|
||||||
position: positionToSpawn,
|
|
||||||
modelURL: Script.resolvePath("models/Stopwatch.fbx"),
|
|
||||||
dimensions: Vec3.multiply(scale, {"x":4.129462242126465,"y":1.058512806892395,"z":5.773681640625}),
|
|
||||||
rotation: Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(90, 0, 0))
|
|
||||||
});
|
|
||||||
|
|
||||||
var secondHandID = Entities.addEntity({
|
|
||||||
type: "Model",
|
|
||||||
name: "stopwatch/seconds",
|
|
||||||
parentID: stopwatchID,
|
|
||||||
localPosition: Vec3.multiply(scale, {"x":-0.004985813982784748,"y":0.39391064643859863,"z":0.8312804698944092}),
|
|
||||||
dimensions: Vec3.multiply(scale, {"x":0.14095762372016907,"y":0.02546107769012451,"z":1.6077008247375488}),
|
|
||||||
registrationPoint: {"x":0.5,"y":0.5,"z":1},
|
|
||||||
modelURL: Script.resolvePath("models/Stopwatch-sec-hand.fbx"),
|
|
||||||
});
|
|
||||||
|
|
||||||
var minuteHandID = Entities.addEntity({
|
|
||||||
type: "Model",
|
|
||||||
name: "stopwatch/minutes",
|
|
||||||
parentID: stopwatchID,
|
|
||||||
localPosition: Vec3.multiply(scale, {"x":-0.0023056098725646734,"y":0.3308190703392029,"z":0.21810021996498108}),
|
|
||||||
dimensions: Vec3.multiply(scale, {"x":0.045471154153347015,"y":0.015412690117955208,"z":0.22930574417114258}),
|
|
||||||
registrationPoint: {"x":0.5,"y":0.5,"z":1},
|
|
||||||
modelURL: Script.resolvePath("models/Stopwatch-min-hand.fbx"),
|
|
||||||
});
|
|
||||||
|
|
||||||
var startStopButtonID = Entities.addEntity({
|
|
||||||
type: "Model",
|
|
||||||
name: "stopwatch/startStop",
|
|
||||||
parentID: stopwatchID,
|
|
||||||
dimensions: Vec3.multiply(scale, { x: 0.8, y: 0.8, z: 1.0 }),
|
|
||||||
localPosition: Vec3.multiply(scale, { x: 0, y: -0.1, z: -2.06 }),
|
|
||||||
modelURL: Script.resolvePath("models/transparent-box.fbx")
|
|
||||||
});
|
|
||||||
|
|
||||||
var resetButtonID = Entities.addEntity({
|
|
||||||
type: "Model",
|
|
||||||
name: "stopwatch/startStop",
|
|
||||||
parentID: stopwatchID,
|
|
||||||
dimensions: Vec3.multiply(scale, { x: 0.6, y: 0.6, z: 0.8 }),
|
|
||||||
localPosition: Vec3.multiply(scale, { x: -1.5, y: -0.1, z: -1.2 }),
|
|
||||||
localRotation: Quat.fromVec3Degrees({ x: 0, y: 36, z: 0 }),
|
|
||||||
modelURL: Script.resolvePath("models/transparent-box.fbx")
|
|
||||||
});
|
|
||||||
|
|
||||||
Entities.editEntity(stopwatchID, {
|
|
||||||
userData: JSON.stringify({
|
|
||||||
secondHandID: secondHandID,
|
|
||||||
minuteHandID: minuteHandID
|
|
||||||
}),
|
|
||||||
serverScripts: Script.resolvePath("stopwatchServer.js")
|
|
||||||
});
|
|
||||||
|
|
||||||
Entities.editEntity(startStopButtonID, {
|
|
||||||
userData: JSON.stringify({
|
|
||||||
stopwatchID: stopwatchID,
|
|
||||||
grabbableKey: { wantsTrigger: true }
|
|
||||||
}),
|
|
||||||
script: Script.resolvePath("stopwatchStartStop.js")
|
|
||||||
});
|
|
||||||
|
|
||||||
Entities.editEntity(resetButtonID, {
|
|
||||||
userData: JSON.stringify({
|
|
||||||
stopwatchID: stopwatchID,
|
|
||||||
grabbableKey: { wantsTrigger: true }
|
|
||||||
}),
|
|
||||||
script: Script.resolvePath("stopwatchReset.js")
|
|
||||||
});
|
|
||||||
|
|
||||||
Script.stop()
|
|
|
@ -1,22 +0,0 @@
|
||||||
//
|
|
||||||
// stopwatchReset.js
|
|
||||||
//
|
|
||||||
// Created by David Rowe on 26 May 2017.
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
this.preload = function (entityID) {
|
|
||||||
var properties = Entities.getEntityProperties(entityID, "userData");
|
|
||||||
this.messageChannel = "STOPWATCH-" + JSON.parse(properties.userData).stopwatchID;
|
|
||||||
};
|
|
||||||
function click() {
|
|
||||||
Messages.sendMessage(this.messageChannel, "reset");
|
|
||||||
}
|
|
||||||
this.startNearTrigger = click;
|
|
||||||
this.startFarTrigger = click;
|
|
||||||
this.clickDownOnEntity = click;
|
|
||||||
});
|
|
|
@ -1,132 +0,0 @@
|
||||||
//
|
|
||||||
// stopwatchServer.js
|
|
||||||
//
|
|
||||||
// Created by Ryan Huffman on 1/20/17.
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.equipped = false;
|
|
||||||
self.isActive = false;
|
|
||||||
self.seconds = 0;
|
|
||||||
|
|
||||||
self.secondHandID = null;
|
|
||||||
self.minuteHandID = null;
|
|
||||||
|
|
||||||
self.tickSound = SoundCache.getSound(Script.resolvePath("sounds/tick.wav"));
|
|
||||||
self.tickInjector = null;
|
|
||||||
self.tickIntervalID = null;
|
|
||||||
|
|
||||||
self.chimeSound = SoundCache.getSound(Script.resolvePath("sounds/chime.wav"));
|
|
||||||
|
|
||||||
self.preload = function(entityID) {
|
|
||||||
print("Preloading stopwatch: ", entityID);
|
|
||||||
self.entityID = entityID;
|
|
||||||
self.messageChannel = "STOPWATCH-" + entityID;
|
|
||||||
|
|
||||||
var userData = Entities.getEntityProperties(self.entityID, 'userData').userData;
|
|
||||||
var data = JSON.parse(userData);
|
|
||||||
self.secondHandID = data.secondHandID;
|
|
||||||
self.minuteHandID = data.minuteHandID;
|
|
||||||
|
|
||||||
self.resetTimer();
|
|
||||||
|
|
||||||
Messages.subscribe(self.messageChannel);
|
|
||||||
Messages.messageReceived.connect(this, self.messageReceived);
|
|
||||||
};
|
|
||||||
self.unload = function() {
|
|
||||||
print("Unloading stopwatch:", self.entityID);
|
|
||||||
self.resetTimer();
|
|
||||||
Messages.unsubscribe(self.messageChannel);
|
|
||||||
Messages.messageReceived.disconnect(this, self.messageReceived);
|
|
||||||
};
|
|
||||||
self.messageReceived = function(channel, message, sender) {
|
|
||||||
print("Message received", channel, sender, message);
|
|
||||||
if (channel === self.messageChannel) {
|
|
||||||
switch (message) {
|
|
||||||
case "startStop":
|
|
||||||
if (self.isActive) {
|
|
||||||
self.stopTimer();
|
|
||||||
} else {
|
|
||||||
self.startTimer();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "reset":
|
|
||||||
self.stopTimer();
|
|
||||||
self.resetTimer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.getStopwatchPosition = function() {
|
|
||||||
return Entities.getEntityProperties(self.entityID, "position").position;
|
|
||||||
};
|
|
||||||
self.resetTimer = function() {
|
|
||||||
print("Resetting stopwatch");
|
|
||||||
Entities.editEntity(self.secondHandID, {
|
|
||||||
localRotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
|
||||||
angularVelocity: { x: 0, y: 0, z: 0 },
|
|
||||||
});
|
|
||||||
Entities.editEntity(self.minuteHandID, {
|
|
||||||
localRotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
|
||||||
angularVelocity: { x: 0, y: 0, z: 0 },
|
|
||||||
});
|
|
||||||
self.seconds = 0;
|
|
||||||
};
|
|
||||||
self.startTimer = function() {
|
|
||||||
print("Starting stopwatch");
|
|
||||||
if (!self.tickInjector) {
|
|
||||||
self.tickInjector = Audio.playSound(self.tickSound, {
|
|
||||||
position: self.getStopwatchPosition(),
|
|
||||||
volume: 0.7,
|
|
||||||
loop: true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self.tickInjector.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tickIntervalID = Script.setInterval(function() {
|
|
||||||
if (self.tickInjector) {
|
|
||||||
self.tickInjector.setOptions({
|
|
||||||
position: self.getStopwatchPosition(),
|
|
||||||
volume: 0.7,
|
|
||||||
loop: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
self.seconds++;
|
|
||||||
const degreesPerTick = -360 / 60;
|
|
||||||
Entities.editEntity(self.secondHandID, {
|
|
||||||
localRotation: Quat.fromPitchYawRollDegrees(0, self.seconds * degreesPerTick, 0),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (self.seconds % 60 == 0) {
|
|
||||||
Entities.editEntity(self.minuteHandID, {
|
|
||||||
localRotation: Quat.fromPitchYawRollDegrees(0, (self.seconds / 60) * degreesPerTick, 0),
|
|
||||||
});
|
|
||||||
Audio.playSound(self.chimeSound, {
|
|
||||||
position: self.getStopwatchPosition(),
|
|
||||||
volume: 1.0,
|
|
||||||
loop: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
self.isActive = true;
|
|
||||||
};
|
|
||||||
self.stopTimer = function () {
|
|
||||||
print("Stopping stopwatch");
|
|
||||||
if (self.tickInjector) {
|
|
||||||
self.tickInjector.stop();
|
|
||||||
}
|
|
||||||
if (self.tickIntervalID !== null) {
|
|
||||||
Script.clearInterval(self.tickIntervalID);
|
|
||||||
self.tickIntervalID = null;
|
|
||||||
}
|
|
||||||
self.isActive = false;
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// stopwatchStartStop.js
|
|
||||||
//
|
|
||||||
// Created by David Rowe on 26 May 2017.
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
var messageChannel;
|
|
||||||
this.preload = function (entityID) {
|
|
||||||
var properties = Entities.getEntityProperties(entityID, "userData");
|
|
||||||
this.messageChannel = "STOPWATCH-" + JSON.parse(properties.userData).stopwatchID;
|
|
||||||
};
|
|
||||||
function click() {
|
|
||||||
Messages.sendMessage(this.messageChannel, "startStop");
|
|
||||||
}
|
|
||||||
this.startNearTrigger = click;
|
|
||||||
this.startFarTrigger = click;
|
|
||||||
this.clickDownOnEntity = click;
|
|
||||||
});
|
|
Loading…
Reference in a new issue