mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 20:48:56 +02:00
bring over some previous tablet-ui work
This commit is contained in:
parent
401f49ff52
commit
369f61e172
15 changed files with 322 additions and 53 deletions
|
@ -1018,7 +1018,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
toggleMenuUnderReticle();
|
toggleMenuUnderReticle();
|
||||||
}
|
}
|
||||||
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
|
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
|
||||||
toggleMenuUnderReticle();
|
toggleTabletUI();
|
||||||
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
||||||
auto oldPos = getApplicationCompositor().getReticlePosition();
|
auto oldPos = getApplicationCompositor().getReticlePosition();
|
||||||
getApplicationCompositor().setReticlePosition({ oldPos.x + state, oldPos.y });
|
getApplicationCompositor().setReticlePosition({ oldPos.x + state, oldPos.y });
|
||||||
|
@ -1484,6 +1484,11 @@ void Application::toggleMenuUnderReticle() const {
|
||||||
offscreenUi->toggleMenu(QPoint(reticlePosition.x - X_LEFT_SHIFT, reticlePosition.y));
|
offscreenUi->toggleMenu(QPoint(reticlePosition.x - X_LEFT_SHIFT, reticlePosition.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::toggleTabletUI() const {
|
||||||
|
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
HMD->toggleShouldShowTablet();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::checkChangeCursor() {
|
void Application::checkChangeCursor() {
|
||||||
QMutexLocker locker(&_changeCursorLock);
|
QMutexLocker locker(&_changeCursorLock);
|
||||||
if (_cursorNeedsChanging) {
|
if (_cursorNeedsChanging) {
|
||||||
|
|
|
@ -455,6 +455,7 @@ private:
|
||||||
|
|
||||||
void maybeToggleMenuVisible(QMouseEvent* event) const;
|
void maybeToggleMenuVisible(QMouseEvent* event) const;
|
||||||
void toggleMenuUnderReticle() const;
|
void toggleMenuUnderReticle() const;
|
||||||
|
void toggleTabletUI() const;
|
||||||
|
|
||||||
MainWindow* _window;
|
MainWindow* _window;
|
||||||
QElapsedTimer& _sessionRunTimer;
|
QElapsedTimer& _sessionRunTimer;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <display-plugins/CompositorHelper.h>
|
#include <display-plugins/CompositorHelper.h>
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
#include <plugins/PluginUtils.h>
|
#include <plugins/PluginUtils.h>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
||||||
Q_PROPERTY(glm::vec3 position READ getPosition)
|
Q_PROPERTY(glm::vec3 position READ getPosition)
|
||||||
Q_PROPERTY(glm::quat orientation READ getOrientation)
|
Q_PROPERTY(glm::quat orientation READ getOrientation)
|
||||||
Q_PROPERTY(bool mounted READ isMounted)
|
Q_PROPERTY(bool mounted READ isMounted)
|
||||||
|
Q_PROPERTY(bool showTablet READ getShouldShowTablet)
|
||||||
|
Q_PROPERTY(QUuid tabletID READ getCurrentTableUIID WRITE setCurrentTabletUIID)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const;
|
Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const;
|
||||||
|
@ -52,11 +54,11 @@ public:
|
||||||
Q_INVOKABLE void disableExtraLaser() const;
|
Q_INVOKABLE void disableExtraLaser() const;
|
||||||
|
|
||||||
|
|
||||||
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
||||||
/// not be interrupted by a keyboard popup
|
/// not be interrupted by a keyboard popup
|
||||||
/// Returns false if there is already an active keyboard displayed.
|
/// Returns false if there is already an active keyboard displayed.
|
||||||
/// Clients should re-enable the keyboard when the operation is complete and ensure
|
/// Clients should re-enable the keyboard when the operation is complete and ensure
|
||||||
/// that they balance any call to suppressKeyboard() that returns true with a corresponding
|
/// that they balance any call to suppressKeyboard() that returns true with a corresponding
|
||||||
/// call to unsuppressKeyboard() within a reasonable amount of time
|
/// call to unsuppressKeyboard() within a reasonable amount of time
|
||||||
Q_INVOKABLE bool suppressKeyboard();
|
Q_INVOKABLE bool suppressKeyboard();
|
||||||
|
|
||||||
|
@ -79,10 +81,19 @@ public:
|
||||||
|
|
||||||
bool isMounted() const;
|
bool isMounted() const;
|
||||||
|
|
||||||
|
void toggleShouldShowTablet() { _showTablet = !_showTablet; }
|
||||||
|
bool getShouldShowTablet() const { return _showTablet; }
|
||||||
|
|
||||||
|
void setCurrentTabletUIID(QUuid tabletID) { _tabletUIID = tabletID; }
|
||||||
|
QUuid getCurrentTableUIID() { return _tabletUIID; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool _showTablet { false };
|
||||||
|
QUuid _tabletUIID; // this is the entityID of the WebEntity which is part of (a child of) the tablet-ui.
|
||||||
|
|
||||||
// Get the position of the HMD
|
// Get the position of the HMD
|
||||||
glm::vec3 getPosition() const;
|
glm::vec3 getPosition() const;
|
||||||
|
|
||||||
// Get the orientation of the HMD
|
// Get the orientation of the HMD
|
||||||
glm::quat getOrientation() const;
|
glm::quat getOrientation() const;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <gl/OffscreenQmlSurface.h>
|
|
||||||
#include <AbstractViewStateInterface.h>
|
#include <AbstractViewStateInterface.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
@ -69,6 +68,8 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
||||||
qWarning() << "Too many concurrent web views to create new view";
|
qWarning() << "Too many concurrent web views to create new view";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
qDebug() << "Building web surface";
|
||||||
|
|
||||||
QString javaScriptToInject;
|
QString javaScriptToInject;
|
||||||
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
|
QFile webChannelFile(":qtwebchannel/qwebchannel.js");
|
||||||
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
|
QFile createGlobalEventBridgeFile(PathUtils::resourcesPath() + "/html/createGlobalEventBridge.js");
|
||||||
|
@ -78,13 +79,13 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
||||||
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
|
QString createGlobalEventBridgeStr = QTextStream(&createGlobalEventBridgeFile).readAll();
|
||||||
|
|
||||||
// concatenate these js files
|
// concatenate these js files
|
||||||
javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
|
_javaScriptToInject = webChannelStr + createGlobalEventBridgeStr;
|
||||||
} else {
|
} else {
|
||||||
qCWarning(entitiesrenderer) << "unable to find qwebchannel.js or createGlobalEventBridge.js";
|
qCWarning(entitiesrenderer) << "unable to find qwebchannel.js or createGlobalEventBridge.js";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the original GL context, because creating a QML surface will create a new context
|
// Save the original GL context, because creating a QML surface will create a new context
|
||||||
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
|
QOpenGLContext* currentContext = QOpenGLContext::currentContext();
|
||||||
if (!currentContext) {
|
if (!currentContext) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -117,23 +118,13 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
||||||
// is no longer valid
|
// is no longer valid
|
||||||
_webSurface->create(currentContext);
|
_webSurface->create(currentContext);
|
||||||
|
|
||||||
#define AJT_TABLET_HACK
|
loadSourceURL();
|
||||||
|
|
||||||
#ifdef AJT_TABLET_HACK
|
|
||||||
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/hifi/tablet/"));
|
|
||||||
_webSurface->load("Tablet.qml", [&](QQmlContext* context, QObject* obj) {
|
|
||||||
;
|
|
||||||
});
|
|
||||||
_webSurface->resume();
|
|
||||||
#else
|
|
||||||
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/"));
|
|
||||||
_webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) {
|
|
||||||
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject));
|
|
||||||
});
|
|
||||||
_webSurface->resume();
|
_webSurface->resume();
|
||||||
|
// _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) {
|
||||||
|
// _texture = textureId;
|
||||||
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||||
_webSurface->getRootContext()->setContextProperty("desktop", QVariant());
|
_webSurface->getRootContext()->setContextProperty("desktop", QVariant());
|
||||||
#endif
|
|
||||||
// FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml.
|
// FIXME - Keyboard HMD only: Possibly add "HMDinfo" object to context for WebView.qml.
|
||||||
|
|
||||||
// forward web events to EntityScriptingInterface
|
// forward web events to EntityScriptingInterface
|
||||||
|
@ -170,7 +161,9 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
||||||
QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, touchPoints);
|
QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, touchPoints);
|
||||||
touchEvent->setWindow(_webSurface->getWindow());
|
touchEvent->setWindow(_webSurface->getWindow());
|
||||||
touchEvent->setDevice(&_touchDevice);
|
touchEvent->setDevice(&_touchDevice);
|
||||||
touchEvent->setTarget(_webSurface->getRootItem());
|
if (_contentType == htmlContent) {
|
||||||
|
touchEvent->setTarget(_webSurface->getRootItem());
|
||||||
|
}
|
||||||
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -256,13 +249,49 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId);
|
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderableWebEntityItem::loadSourceURL() {
|
||||||
|
QUrl sourceUrl(_sourceUrl);
|
||||||
|
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
||||||
|
_sourceUrl.toLower().endsWith(".htm") || _sourceUrl.toLower().endsWith(".html")) {
|
||||||
|
|
||||||
|
qDebug() << "HERE RenderableWebEntityItem::loadSourceURL http -- " << _sourceUrl;
|
||||||
|
|
||||||
|
_contentType = htmlContent;
|
||||||
|
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/"));
|
||||||
|
|
||||||
|
QString fuh = QUrl::fromLocalFile(PathUtils::resourcesPath()).toString() + "qml/controls/" + "WebView.qml";
|
||||||
|
qDebug() << "HERE full name is " << fuh;
|
||||||
|
|
||||||
|
_webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) {
|
||||||
|
context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject));
|
||||||
|
});
|
||||||
|
// _webSurface->getRootItem()->setProperty("eventBridge", QVariant::fromValue(_webEntityAPIHelper));
|
||||||
|
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||||
|
_webSurface->getRootContext()->setContextProperty("desktop", QVariant());
|
||||||
|
// _webSurface->getRootContext()->setContextProperty("webEntity", _webEntityAPIHelper);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qDebug() << "HERE RenderableWebEntityItem::loadSourceURL qml -- " << _sourceUrl;
|
||||||
|
|
||||||
|
_contentType = qmlContent;
|
||||||
|
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
||||||
|
_webSurface->load(_sourceUrl, [&](QQmlContext* context, QObject* obj) { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderableWebEntityItem::setSourceUrl(const QString& value) {
|
void RenderableWebEntityItem::setSourceUrl(const QString& value) {
|
||||||
if (_sourceUrl != value) {
|
if (_sourceUrl != value) {
|
||||||
qDebug() << "Setting web entity source URL to " << value;
|
qDebug() << "Setting web entity source URL to " << value;
|
||||||
_sourceUrl = value;
|
_sourceUrl = value;
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
|
qDebug() << "HERE RenderableWebEntityItem::setSourceUrl has _webSurface";
|
||||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||||
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
qDebug() << "HERE RenderableWebEntityItem::setSourceUrl in lambda";
|
||||||
|
loadSourceURL();
|
||||||
|
if (_contentType == htmlContent) {
|
||||||
|
_webSurface->getRootItem()->setProperty("url", _sourceUrl);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +362,9 @@ void RenderableWebEntityItem::handlePointerEvent(const PointerEvent& event) {
|
||||||
QTouchEvent* touchEvent = new QTouchEvent(type);
|
QTouchEvent* touchEvent = new QTouchEvent(type);
|
||||||
touchEvent->setWindow(_webSurface->getWindow());
|
touchEvent->setWindow(_webSurface->getWindow());
|
||||||
touchEvent->setDevice(&_touchDevice);
|
touchEvent->setDevice(&_touchDevice);
|
||||||
touchEvent->setTarget(_webSurface->getRootItem());
|
if (_contentType == htmlContent) {
|
||||||
|
touchEvent->setTarget(_webSurface->getRootItem());
|
||||||
|
}
|
||||||
touchEvent->setTouchPoints(touchPoints);
|
touchEvent->setTouchPoints(touchPoints);
|
||||||
touchEvent->setTouchPointStates(touchPointState);
|
touchEvent->setTouchPointStates(touchPointState);
|
||||||
|
|
||||||
|
@ -385,6 +416,74 @@ bool RenderableWebEntityItem::isTransparent() {
|
||||||
return fadeRatio < OPAQUE_ALPHA_THRESHOLD;
|
return fadeRatio < OPAQUE_ALPHA_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject* RenderableWebEntityItem::getRootItem() {
|
||||||
|
if (_webSurface) {
|
||||||
|
return dynamic_cast<QObject*>(_webSurface->getRootItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "HERE no _websurface";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// UTF-8 encoded symbols
|
||||||
|
static const uint8_t UPWARDS_WHITE_ARROW_FROM_BAR[] = { 0xE2, 0x87, 0xAA, 0x00 }; // shift
|
||||||
|
static const uint8_t LEFT_ARROW[] = { 0xE2, 0x86, 0x90, 0x00 }; // backspace
|
||||||
|
static const uint8_t LEFTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA6, 0x00 }; // left arrow
|
||||||
|
static const uint8_t RIGHTWARD_WHITE_ARROW[] = { 0xE2, 0x87, 0xA8, 0x00 }; // right arrow
|
||||||
|
static const uint8_t ASTERISIM[] = { 0xE2, 0x81, 0x82, 0x00 }; // symbols
|
||||||
|
static const uint8_t RETURN_SYMBOL[] = { 0xE2, 0x8F, 0x8E, 0x00 }; // return
|
||||||
|
static const char PUNCTUATION_STRING[] = "&123";
|
||||||
|
static const char ALPHABET_STRING[] = "abc";
|
||||||
|
|
||||||
|
static bool equals(const QByteArray& byteArray, const uint8_t* ptr) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < byteArray.size(); i++) {
|
||||||
|
if ((char)ptr[i] != byteArray[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ptr[i] == 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableWebEntityItem::synthesizeKeyPress(QString key) {
|
||||||
|
auto utf8Key = key.toUtf8();
|
||||||
|
|
||||||
|
int scanCode = (int)utf8Key[0];
|
||||||
|
QString keyString = key;
|
||||||
|
if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) ||
|
||||||
|
equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) {
|
||||||
|
return; // ignore
|
||||||
|
} else if (equals(utf8Key, LEFT_ARROW)) {
|
||||||
|
scanCode = Qt::Key_Backspace;
|
||||||
|
keyString = "\x08";
|
||||||
|
} else if (equals(utf8Key, RETURN_SYMBOL)) {
|
||||||
|
scanCode = Qt::Key_Return;
|
||||||
|
keyString = "\x0d";
|
||||||
|
} else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) {
|
||||||
|
scanCode = Qt::Key_Left;
|
||||||
|
keyString = "";
|
||||||
|
} else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) {
|
||||||
|
scanCode = Qt::Key_Right;
|
||||||
|
keyString = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString);
|
||||||
|
QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString);
|
||||||
|
QCoreApplication::postEvent(getEventHandler(), pressEvent);
|
||||||
|
QCoreApplication::postEvent(getEventHandler(), releaseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void RenderableWebEntityItem::setKeyboardRaised(bool raised) {
|
||||||
|
//
|
||||||
|
// // raise the keyboard only while in HMD mode and it's being requested.
|
||||||
|
// bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised;
|
||||||
|
//
|
||||||
|
// if (_contentType == htmlContent) {
|
||||||
|
// _webSurface->getRootItem()->setProperty("keyboardRaised", QVariant(value));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) {
|
void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) {
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
_webSurface->emitScriptEvent(message);
|
_webSurface->emitScriptEvent(message);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <gl/OffscreenQmlSurface.h>
|
#include <gl/OffscreenQmlSurface.h>
|
||||||
|
|
||||||
#include <WebEntityItem.h>
|
#include <WebEntityItem.h>
|
||||||
|
#include <gl/OffscreenQmlSurface.h>
|
||||||
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ public:
|
||||||
~RenderableWebEntityItem();
|
~RenderableWebEntityItem();
|
||||||
|
|
||||||
virtual void render(RenderArgs* args) override;
|
virtual void render(RenderArgs* args) override;
|
||||||
|
void loadSourceURL();
|
||||||
virtual void setSourceUrl(const QString& value) override;
|
virtual void setSourceUrl(const QString& value) override;
|
||||||
|
|
||||||
virtual bool wantsHandControllerPointerEvents() const override { return true; }
|
virtual bool wantsHandControllerPointerEvents() const override { return true; }
|
||||||
|
@ -51,6 +53,11 @@ public:
|
||||||
|
|
||||||
virtual bool isTransparent() override;
|
virtual bool isTransparent() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void synthesizeKeyPress(QString key);
|
||||||
|
|
||||||
|
QObject* getRootItem() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool buildWebSurface(QSharedPointer<EntityTreeRenderer> renderer);
|
bool buildWebSurface(QSharedPointer<EntityTreeRenderer> renderer);
|
||||||
void destroyWebSurface();
|
void destroyWebSurface();
|
||||||
|
@ -69,6 +76,14 @@ private:
|
||||||
QMetaObject::Connection _mouseReleaseConnection;
|
QMetaObject::Connection _mouseReleaseConnection;
|
||||||
QMetaObject::Connection _mouseMoveConnection;
|
QMetaObject::Connection _mouseMoveConnection;
|
||||||
QMetaObject::Connection _hoverLeaveConnection;
|
QMetaObject::Connection _hoverLeaveConnection;
|
||||||
|
|
||||||
|
QString _javaScriptToInject;
|
||||||
|
|
||||||
|
enum contentType {
|
||||||
|
htmlContent,
|
||||||
|
qmlContent
|
||||||
|
};
|
||||||
|
contentType _contentType;
|
||||||
int _geometryId { 0 };
|
int _geometryId { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "QVariantGLM.h"
|
#include "QVariantGLM.h"
|
||||||
#include "SimulationOwner.h"
|
#include "SimulationOwner.h"
|
||||||
#include "ZoneEntityItem.h"
|
#include "ZoneEntityItem.h"
|
||||||
|
#include "WebEntityItem.h"
|
||||||
|
|
||||||
EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) :
|
EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) :
|
||||||
_entityTree(NULL),
|
_entityTree(NULL),
|
||||||
|
@ -1453,3 +1453,13 @@ void EntityScriptingInterface::setCostMultiplier(float value) {
|
||||||
costMultiplier = value;
|
costMultiplier = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject* EntityScriptingInterface::getWebViewRoot(const QUuid& entityID) {
|
||||||
|
if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Web)) {
|
||||||
|
auto webEntity = std::dynamic_pointer_cast<WebEntityItem>(entity);
|
||||||
|
QObject* root = webEntity->getRootItem();
|
||||||
|
qDebug() << "HERE getWebViewRoot root =" << ((void*) root);
|
||||||
|
return root;
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -276,6 +276,8 @@ public slots:
|
||||||
|
|
||||||
Q_INVOKABLE void emitScriptEvent(const EntityItemID& entityID, const QVariant& message);
|
Q_INVOKABLE void emitScriptEvent(const EntityItemID& entityID, const QVariant& message);
|
||||||
|
|
||||||
|
Q_INVOKABLE QObject* getWebViewRoot(const QUuid& entityID);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@ public:
|
||||||
void setDPI(uint16_t value);
|
void setDPI(uint16_t value);
|
||||||
uint16_t getDPI() const;
|
uint16_t getDPI() const;
|
||||||
|
|
||||||
|
virtual QObject* getRootItem() { return nullptr; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString _sourceUrl;
|
QString _sourceUrl;
|
||||||
uint16_t _dpi;
|
uint16_t _dpi;
|
||||||
|
|
|
@ -34,7 +34,8 @@ var DEFAULT_SCRIPTS = [
|
||||||
"system/firstPersonHMD.js",
|
"system/firstPersonHMD.js",
|
||||||
"system/snapshot.js",
|
"system/snapshot.js",
|
||||||
"system/help.js",
|
"system/help.js",
|
||||||
"system/bubble.js"
|
"system/bubble.js",
|
||||||
|
"system/tablet-ui/tablet-ui.js"
|
||||||
];
|
];
|
||||||
|
|
||||||
// add a menu item for debugging
|
// add a menu item for debugging
|
||||||
|
|
|
@ -1267,6 +1267,9 @@ function MyController(hand) {
|
||||||
var grabbableProps = entityPropertiesCache.getGrabbableProps(entityID);
|
var grabbableProps = entityPropertiesCache.getGrabbableProps(entityID);
|
||||||
var grabProps = entityPropertiesCache.getGrabProps(entityID);
|
var grabProps = entityPropertiesCache.getGrabProps(entityID);
|
||||||
var props = entityPropertiesCache.getProps(entityID);
|
var props = entityPropertiesCache.getProps(entityID);
|
||||||
|
if (!props) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var physical = propsArePhysical(props);
|
var physical = propsArePhysical(props);
|
||||||
var grabbable = false;
|
var grabbable = false;
|
||||||
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME);
|
||||||
|
@ -1546,7 +1549,7 @@ function MyController(hand) {
|
||||||
Entities.sendHoverOverEntity(entity, pointerEvent);
|
Entities.sendHoverOverEntity(entity, pointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.triggerSmoothedGrab() && !isEditing()) {
|
if (this.triggerSmoothedGrab() && (!isEditing() || name == "WebTablet Web")) {
|
||||||
this.grabbedEntity = entity;
|
this.grabbedEntity = entity;
|
||||||
this.setState(STATE_ENTITY_TOUCHING, "begin touching entity '" + name + "'");
|
this.setState(STATE_ENTITY_TOUCHING, "begin touching entity '" + name + "'");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -39,54 +39,72 @@ function calcSpawnInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ctor
|
// ctor
|
||||||
WebTablet = function (url, width, dpi, clientOnly) {
|
WebTablet = function (url, width, dpi, location, clientOnly) {
|
||||||
|
|
||||||
var ASPECT = 4.0 / 3.0;
|
var ASPECT = 4.0 / 3.0;
|
||||||
var WIDTH = width || DEFAULT_WIDTH;
|
var WIDTH = width || DEFAULT_WIDTH;
|
||||||
var HEIGHT = WIDTH * ASPECT;
|
var HEIGHT = WIDTH * ASPECT;
|
||||||
var DEPTH = 0.025;
|
var DEPTH = 0.025;
|
||||||
var DPI = dpi || DEFAULT_DPI;
|
var DPI = dpi || DEFAULT_DPI;
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
var spawnInfo = calcSpawnInfo();
|
var tabletProperties = {
|
||||||
|
name: "WebTablet Tablet",
|
||||||
var tabletEntityPosition = spawnInfo.position;
|
|
||||||
var tabletEntityRotation = spawnInfo.rotation;
|
|
||||||
this.tabletEntityID = Entities.addEntity({
|
|
||||||
name: "tablet",
|
|
||||||
type: "Model",
|
type: "Model",
|
||||||
modelURL: TABLET_URL,
|
modelURL: TABLET_URL,
|
||||||
position: tabletEntityPosition,
|
|
||||||
rotation: tabletEntityRotation,
|
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
"grabbableKey": {"grabbable": true}
|
"grabbableKey": {"grabbable": true}
|
||||||
}),
|
}),
|
||||||
dimensions: {x: WIDTH, y: HEIGHT, z: DEPTH},
|
dimensions: {x: WIDTH, y: HEIGHT, z: DEPTH},
|
||||||
parentID: MyAvatar.sessionUUID,
|
parentID: MyAvatar.sessionUUID,
|
||||||
parentJointIndex: -2
|
parentJointIndex: -2
|
||||||
}, clientOnly);
|
}
|
||||||
|
|
||||||
|
if (location) {
|
||||||
|
tabletProperties.localPosition = location.localPosition;
|
||||||
|
tabletProperties.localRotation = location.localRotation;
|
||||||
|
} else {
|
||||||
|
var spawnInfo = calcSpawnInfo();
|
||||||
|
tabletProperties.position = spawnInfo.position;
|
||||||
|
tabletProperties.rotation = spawnInfo.rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tabletEntityID = Entities.addEntity(tabletProperties, clientOnly);
|
||||||
|
|
||||||
var WEB_ENTITY_REDUCTION_FACTOR = {x: 0.78, y: 0.85};
|
var WEB_ENTITY_REDUCTION_FACTOR = {x: 0.78, y: 0.85};
|
||||||
var WEB_ENTITY_Z_OFFSET = -0.01;
|
var WEB_ENTITY_Z_OFFSET = -0.01;
|
||||||
|
|
||||||
var webEntityRotation = Quat.multiply(spawnInfo.rotation, Quat.angleAxis(180, Y_AXIS));
|
this.createWebEntity = function(url) {
|
||||||
var webEntityPosition = Vec3.sum(spawnInfo.position, Vec3.multiply(WEB_ENTITY_Z_OFFSET, Quat.getFront(webEntityRotation)));
|
if (_this.webEntityID) {
|
||||||
|
Entities.deleteEntity(_this.webEntityID);
|
||||||
|
}
|
||||||
|
_this.webEntityID = Entities.addEntity({
|
||||||
|
name: "WebTablet Web",
|
||||||
|
type: "Web",
|
||||||
|
sourceUrl: url,
|
||||||
|
dimensions: {x: WIDTH * WEB_ENTITY_REDUCTION_FACTOR.x,
|
||||||
|
y: HEIGHT * WEB_ENTITY_REDUCTION_FACTOR.y,
|
||||||
|
z: 0.1},
|
||||||
|
localPosition: { x: 0, y: 0, z: WEB_ENTITY_Z_OFFSET },
|
||||||
|
localRotation: Quat.angleAxis(180, Y_AXIS),
|
||||||
|
shapeType: "box",
|
||||||
|
dpi: DPI,
|
||||||
|
parentID: _this.tabletEntityID,
|
||||||
|
parentJointIndex: -1
|
||||||
|
}, clientOnly);
|
||||||
|
}
|
||||||
|
|
||||||
this.webEntityID = Entities.addEntity({
|
this.createWebEntity(url);
|
||||||
name: "web",
|
|
||||||
type: "Web",
|
|
||||||
sourceUrl: url,
|
|
||||||
dimensions: {x: WIDTH * WEB_ENTITY_REDUCTION_FACTOR.x,
|
|
||||||
y: HEIGHT * WEB_ENTITY_REDUCTION_FACTOR.y,
|
|
||||||
z: 0.1},
|
|
||||||
position: webEntityPosition,
|
|
||||||
rotation: webEntityRotation,
|
|
||||||
shapeType: "box",
|
|
||||||
dpi: DPI,
|
|
||||||
parentID: this.tabletEntityID,
|
|
||||||
parentJointIndex: -1
|
|
||||||
}, clientOnly);
|
|
||||||
|
|
||||||
this.state = "idle";
|
this.state = "idle";
|
||||||
|
|
||||||
|
this.getRoot = function() {
|
||||||
|
return Entities.getWebViewRoot(_this.webEntityID);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getLocation = function() {
|
||||||
|
return Entities.getEntityProperties(_this.tabletEntityID, ["localPosition", "localRotation"]);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
WebTablet.prototype.destroy = function () {
|
WebTablet.prototype.destroy = function () {
|
||||||
|
|
|
@ -1032,9 +1032,20 @@ SelectionDisplay = (function() {
|
||||||
var pickRay = controllerComputePickRay();
|
var pickRay = controllerComputePickRay();
|
||||||
if (pickRay) {
|
if (pickRay) {
|
||||||
var entityIntersection = Entities.findRayIntersection(pickRay, true);
|
var entityIntersection = Entities.findRayIntersection(pickRay, true);
|
||||||
|
|
||||||
|
|
||||||
var overlayIntersection = Overlays.findRayIntersection(pickRay);
|
var overlayIntersection = Overlays.findRayIntersection(pickRay);
|
||||||
if (entityIntersection.intersects &&
|
if (entityIntersection.intersects &&
|
||||||
(!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) {
|
(!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) {
|
||||||
|
|
||||||
|
// if (entityIntersection.properties.name == "WebTablet Web") {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (HMD.tabletID == entityIntersection.entityID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
selectionManager.setSelections([entityIntersection.entityID]);
|
selectionManager.setSelections([entityIntersection.entityID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,20 @@ function shouldShowWebTablet() {
|
||||||
function showMarketplace(marketplaceID) {
|
function showMarketplace(marketplaceID) {
|
||||||
if (shouldShowWebTablet()) {
|
if (shouldShowWebTablet()) {
|
||||||
updateButtonState(true);
|
updateButtonState(true);
|
||||||
marketplaceWebTablet = new WebTablet("https://metaverse.highfidelity.com/marketplace", null, null, true);
|
|
||||||
|
print("HERE shouldShowWebTablet");
|
||||||
|
if (HMD.tabletID) {
|
||||||
|
print("HERE shouldShowWebTablet tabletID is ", HMD.tabletID);
|
||||||
|
UIWebTablet.createWebEntity("https://metaverse.highfidelity.com/marketplace");
|
||||||
|
HMD.tabletID = UIWebTablet.webEntityID;
|
||||||
|
} else {
|
||||||
|
print("HERE shouldShowWebTablet making new tablet");
|
||||||
|
marketplaceWebTablet = new WebTablet("https://metaverse.highfidelity.com/marketplace",
|
||||||
|
null, // width
|
||||||
|
null, // dpi
|
||||||
|
null, // location
|
||||||
|
true); // client-only
|
||||||
|
}
|
||||||
Settings.setValue(persistenceKey, marketplaceWebTablet.pickle());
|
Settings.setValue(persistenceKey, marketplaceWebTablet.pickle());
|
||||||
} else {
|
} else {
|
||||||
var url = MARKETPLACE_URL;
|
var url = MARKETPLACE_URL;
|
||||||
|
|
77
scripts/system/tablet-ui/tablet-ui.js
Normal file
77
scripts/system/tablet-ui/tablet-ui.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
//
|
||||||
|
// tablet-ui.js
|
||||||
|
//
|
||||||
|
// scripts/system/tablet-ui/
|
||||||
|
//
|
||||||
|
// Created by Seth Alves 2016-9-29
|
||||||
|
// Copyright 2016 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
|
||||||
|
//
|
||||||
|
|
||||||
|
/* global Script, HMD, WebTablet, UIWebTablet */
|
||||||
|
|
||||||
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
var tabletShown = false;
|
||||||
|
var tabletLocation = null;
|
||||||
|
|
||||||
|
Script.include("../libraries/WebTablet.js");
|
||||||
|
|
||||||
|
function showTabletUI() {
|
||||||
|
tabletShown = true;
|
||||||
|
print("show tablet-ui");
|
||||||
|
// var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||||
|
UIWebTablet = new WebTablet("qml/desktop/TabletUI.qml", null, null, tabletLocation);
|
||||||
|
HMD.tabletID = UIWebTablet.webEntityID;
|
||||||
|
|
||||||
|
var setUpTabletUI = function() {
|
||||||
|
var root = UIWebTablet.getRoot();
|
||||||
|
if (!root) {
|
||||||
|
print("HERE no root yet");
|
||||||
|
Script.setTimeout(setUpTabletUI, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print("HERE got root", root);
|
||||||
|
var buttons = Toolbars.getToolbarButtons("com.highfidelity.interface.toolbar.system");
|
||||||
|
print("HERE got buttons: ", buttons.length);
|
||||||
|
for (var i = 0; i < buttons.length; i++) {
|
||||||
|
print("HERE hooking up button: ", buttons[i].objectName);
|
||||||
|
Toolbars.hookUpButtonClone("com.highfidelity.interface.toolbar.system", root, buttons[i]);
|
||||||
|
}
|
||||||
|
// UserActivityLogger.openedTabletUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.setTimeout(setUpTabletUI, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideTabletUI() {
|
||||||
|
tabletShown = false;
|
||||||
|
print("hide tablet-ui");
|
||||||
|
if (UIWebTablet) {
|
||||||
|
if (UIWebTablet.onClose) {
|
||||||
|
UIWebTablet.onClose();
|
||||||
|
}
|
||||||
|
Toolbars.destroyButtonClones("com.highfidelity.interface.toolbar.system");
|
||||||
|
|
||||||
|
tabletLocation = UIWebTablet.getLocation();
|
||||||
|
UIWebTablet.destroy();
|
||||||
|
UIWebTablet = null;
|
||||||
|
HMD.tabletID = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateShowTablet() {
|
||||||
|
if (HMD.showTablet && !tabletShown) {
|
||||||
|
showTabletUI();
|
||||||
|
} else if (!HMD.showTablet && tabletShown) {
|
||||||
|
hideTabletUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(updateShowTablet);
|
||||||
|
// Script.setInterval(updateShowTablet, 1000);
|
||||||
|
|
||||||
|
}()); // END LOCAL_SCOPE
|
Loading…
Reference in a new issue