diff --git a/interface/resources/html/interface-welcome.html b/interface/resources/html/interface-welcome.html index 26ae6ff5c0..1fc719ed72 100644 --- a/interface/resources/html/interface-welcome.html +++ b/interface/resources/html/interface-welcome.html @@ -1,8 +1,7 @@ - - + Welcome to Interface @@ -85,63 +84,63 @@

Move around

- + Move around

- Move around with WASD & fly
- up or down with E & C.
- Cmnd/Ctrl+G will send you
- home. Hitting Enter will let you
+ Move around with WASD & fly
+ up or down with E & C.
+ Cmnd/Ctrl+G will send you
+ home. Hitting Enter will let you
teleport to a user or location.

-

Listen & talk

- +

Listen & talk

+ Talk

- Use your best headphones
- and microphone for high
- fidelity audio. Chat via text by
+ Use your best headphones
+ and microphone for high
+ fidelity audio. Chat via text by
pressing the \ key.

Connect devices

- + Connect devices

- Have an Oculus Rift, a Razer
- Hydra, or a PrimeSense 3D
+ Have an Oculus Rift, a Razer
+ Hydra, or a PrimeSense 3D
camera? We support them all.

Run a script

- + Run a script

- Cmnd/Cntrl+J will launch a
- Running Scripts dialog to help
- manage your scripts and search
+ Cmnd/Cntrl+J will launch a
+ Running Scripts dialog to help
+ manage your scripts and search
for new ones to run.

Script something

- + Write a script

- Write a script; we're always
- adding new features.
- Cmnd/Cntrl+J will launch a
- Running Scripts dialog to help
+ Write a script; we're always
+ adding new features.
+ Cmnd/Cntrl+J will launch a
+ Running Scripts dialog to help
manage your scripts.

Import models

- + Import models

- Use the edit.js script to
- add FBX models in-world. You
- can use grids and fine tune
- placement-related parameters
+ Use the edit.js script to
+ add FBX models in-world. You
+ can use grids and fine tune
+ placement-related parameters
with ease.

@@ -149,20 +148,19 @@

Read the docs

- We are writing documentation on
- just about everything. Please,
- devour all we've written and make
- suggestions where necessary.
- Documentation is always at
+ We are writing documentation on
+ just about everything. Please,
+ devour all we've written and make
+ suggestions where necessary.
+ Documentation is always at
docs.highfidelity.com

-
- +//]]> diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index a439f9114c..55a0a6a461 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -2,29 +2,149 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtWebKit 3.0 import "controls" +import "styles" Dialog { - title: "Browser Window" - id: testDialog - objectName: "Browser" - width: 1280 - height: 720 + id: root + HifiConstants { id: hifi } + title: "Browser" + resizable: true + contentImplicitWidth: clientArea.implicitWidth + contentImplicitHeight: clientArea.implicitHeight + backgroundColor: "#7f000000" + + + Component.onCompleted: { + enabled = true + addressBar.text = webview.url + } + + onParentChanged: { + if (visible && enabled) { + addressBar.forceActiveFocus(); + addressBar.selectAll() + } + } Item { id: clientArea - // The client area - anchors.fill: parent - anchors.margins: parent.margins - anchors.topMargin: parent.topMargin - + implicitHeight: 600 + implicitWidth: 800 + x: root.clientX + y: root.clientY + width: root.clientWidth + height: root.clientHeight + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: scrollView.top + color: "white" + } + Row { + id: buttons + spacing: 4 + anchors.top: parent.top + anchors.topMargin: 8 + anchors.left: parent.left + anchors.leftMargin: 8 + FontAwesome { + id: back; text: "\uf0a8"; size: 48; enabled: webview.canGoBack; + color: enabled ? hifi.colors.text : hifi.colors.disabledText + MouseArea { anchors.fill: parent; onClicked: webview.goBack() } + } + FontAwesome { + id: forward; text: "\uf0a9"; size: 48; enabled: webview.canGoForward; + color: enabled ? hifi.colors.text : hifi.colors.disabledText + MouseArea { anchors.fill: parent; onClicked: webview.goBack() } + } + FontAwesome { + id: reload; size: 48; text: webview.loading ? "\uf057" : "\uf021" + MouseArea { anchors.fill: parent; onClicked: webview.loading ? webview.stop() : webview.reload() } + } + } + + Border { + height: 48 + radius: 8 + anchors.top: parent.top + anchors.topMargin: 8 + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.left: buttons.right + anchors.leftMargin: 8 + + Item { + id: barIcon + width: parent.height + height: parent.height + Image { + source: webview.icon; + x: (parent.height - height) / 2 + y: (parent.width - width) / 2 + verticalAlignment: Image.AlignVCenter; + horizontalAlignment: Image.AlignHCenter + onSourceChanged: console.log("Icon url: " + source) + } + } + + TextInput { + id: addressBar + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.left: barIcon.right + anchors.leftMargin: 0 + anchors.verticalCenter: parent.verticalCenter + + Keys.onPressed: { + switch(event.key) { + case Qt.Key_Enter: + case Qt.Key_Return: + event.accepted = true + if (text.indexOf("http") != 0) { + text = "http://" + text + } + webview.url = text + break; + } + } + } + } + ScrollView { - anchors.fill: parent + id: scrollView + anchors.top: buttons.bottom + anchors.topMargin: 8 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right WebView { id: webview - url: "http://slashdot.org" + url: "http://highfidelity.com" anchors.fill: parent + onLoadingChanged: { + if (loadRequest.status == WebView.LoadSucceededStarted) { + addressBar.text = loadRequest.url + } + } + onIconChanged: { + barIcon.source = icon + } } - } - - } -} + } + } // item + + Keys.onPressed: { + switch(event.key) { + case Qt.Key_L: + if (event.modifiers == Qt.ControlModifier) { + event.accepted = true + addressBar.selectAll() + addressBar.forceActiveFocus() + } + break; + } + } + +} // dialog diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml new file mode 100644 index 0000000000..6b49e6f0c7 --- /dev/null +++ b/interface/resources/qml/InfoView.qml @@ -0,0 +1,32 @@ +import Hifi 1.0 as Hifi +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.3 +import QtWebKit 3.0 +import "controls" + +Dialog { + id: root + width: 800 + height: 800 + resizable: true + + Hifi.InfoView { + id: infoView + // Fille the client area + anchors.fill: parent + anchors.margins: parent.margins + anchors.topMargin: parent.topMargin + + ScrollView { + anchors.fill: parent + WebView { + objectName: "WebView" + id: webview + url: infoView.url + anchors.fill: parent + } + } + + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c9842b777..b1ef689599 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -85,7 +85,7 @@ #include #include #include - +#include #include #include "Application.h" @@ -134,7 +134,6 @@ #include "ui/DataWebDialog.h" #include "ui/DialogsManager.h" -#include "ui/InfoView.h" #include "ui/LoginDialog.h" #include "ui/Snapshot.h" #include "ui/StandAloneJSConsole.h" @@ -777,8 +776,8 @@ void Application::initializeGL() { // update before the first render update(1.0f / _fps); - - InfoView::showFirstTime(INFO_HELP_PATH); + + InfoView::show(INFO_HELP_PATH, true); } void Application::initializeUi() { @@ -942,11 +941,11 @@ void Application::faceTrackerMuteToggled() { } void Application::aboutApp() { - InfoView::forcedShow(INFO_HELP_PATH); + InfoView::show(INFO_HELP_PATH); } void Application::showEditEntitiesHelp() { - InfoView::forcedShow(INFO_EDIT_ENTITIES_PATH); + InfoView::show(INFO_EDIT_ENTITIES_PATH); } void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) { @@ -1133,6 +1132,13 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::AddressBar); break; + case Qt::Key_B: + if (isMeta) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->load("Browser.qml"); + } + break; + case Qt::Key_L: if (isShifted && isMeta) { Menu::getInstance()->triggerOption(MenuOption::Log); @@ -2313,18 +2319,6 @@ void Application::updateCamera(float deltaTime) { PerformanceTimer perfTimer("updateCamera"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCamera()"); - - if (!OculusManager::isConnected() && !TV3DManager::isConnected() && - Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { - FaceTracker* tracker = getActiveFaceTracker(); - if (tracker && !tracker->isMuted()) { - const float EYE_OFFSET_SCALE = 0.025f; - glm::vec3 position = tracker->getHeadTranslation() * EYE_OFFSET_SCALE; - float xSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? 1.0f : -1.0f; - _myCamera.setEyeOffsetPosition(glm::vec3(position.x * xSign, position.y, -position.z)); - updateProjectionMatrix(); - } - } } void Application::updateDialogs(float deltaTime) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b6940566ad..405f98c8d7 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -282,7 +282,6 @@ Menu::Menu() { Qt::CTRL | Qt::SHIFT | Qt::Key_1, false, &nodeBounds, SLOT(setShowEntityNodes(bool))); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a622668742..b15607df8f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -214,7 +214,6 @@ namespace MenuOption { const QString MuteFaceTracking = "Mute Face Tracking"; const QString NoFaceTracking = "None"; const QString OctreeStats = "Entity Statistics"; - const QString OffAxisProjection = "Off-Axis Projection"; const QString OnlyDisplayTopTen = "Only Display Top Ten"; const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; diff --git a/interface/src/ui/InfoView.cpp b/interface/src/ui/InfoView.cpp deleted file mode 100644 index b62b8f3f2d..0000000000 --- a/interface/src/ui/InfoView.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// InfoView.cpp -// interface/src/ui -// -// Created by Stojce Slavkovski on 9/7/13. -// Copyright 2013 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 -// - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "InfoView.h" - -static const float MAX_DIALOG_HEIGHT_RATIO = 0.9f; - -Setting::Handle infoVersion("info-version", QString()); - -InfoView::InfoView(bool forced, QString path) : - _forced(forced) -{ - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); - - QString absPath = QFileInfo(PathUtils::resourcesPath() + path).absoluteFilePath(); - QUrl url = QUrl::fromLocalFile(absPath); - - page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks); - connect(this, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClickedInfoView(QUrl))); - - load(url); - connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loaded(bool))); -} - -void InfoView::showFirstTime(QString path) { - new InfoView(false, path); -} - -void InfoView::forcedShow(QString path) { - new InfoView(true, path); -} - -bool InfoView::shouldShow() { - bool shouldShow = false; - if (_forced) { - return true; - } - - QString lastVersion = infoVersion.get(); - - QWebElement versionTag = page()->mainFrame()->findFirstElement("#version"); - QString version = versionTag.attribute("value"); - - if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) { - infoVersion.set(version); - shouldShow = true; - } else { - shouldShow = false; - } - return shouldShow; -} - -void InfoView::loaded(bool ok) { - if (!ok || !shouldShow()) { - deleteLater(); - return; - } - - QDesktopWidget* desktop = qApp->desktop(); - QWebFrame* mainFrame = page()->mainFrame(); - - int height = mainFrame->contentsSize().height() > desktop->height() ? - desktop->height() * MAX_DIALOG_HEIGHT_RATIO : - mainFrame->contentsSize().height(); - - resize(mainFrame->contentsSize().width(), height); - move(desktop->screen()->rect().center() - rect().center()); - setWindowTitle(title()); - setAttribute(Qt::WA_DeleteOnClose); - show(); -} - -void InfoView::linkClickedInfoView(QUrl url) { - close(); - QDesktopServices::openUrl(url); -} diff --git a/interface/src/ui/InfoView.h b/interface/src/ui/InfoView.h deleted file mode 100644 index 1198a703e4..0000000000 --- a/interface/src/ui/InfoView.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// InfoView.h -// interface/src/ui -// -// Created by Stojce Slavkovski on 9/7/13. -// Copyright 2013 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 -// - -#ifndef hifi_InfoView_h -#define hifi_InfoView_h - -#include - -class InfoView : public QWebView { - Q_OBJECT -public: - static void showFirstTime(QString path); - static void forcedShow(QString path); - -private: - InfoView(bool forced, QString path); - bool _forced; - bool shouldShow(); - -private slots: - void loaded(bool ok); - void linkClickedInfoView(QUrl url); -}; - -#endif // hifi_InfoView_h diff --git a/libraries/ui/CMakeLists.txt b/libraries/ui/CMakeLists.txt index 36a0a1a846..1aefc99c78 100644 --- a/libraries/ui/CMakeLists.txt +++ b/libraries/ui/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME ui) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(OpenGL Network Qml Quick Script) +setup_hifi_library(OpenGL Network Qml Quick Script XmlPatterns) link_hifi_libraries(render-utils shared) diff --git a/libraries/ui/src/InfoView.cpp b/libraries/ui/src/InfoView.cpp new file mode 100644 index 0000000000..3f80c97c4c --- /dev/null +++ b/libraries/ui/src/InfoView.cpp @@ -0,0 +1,87 @@ +// +// +// InfoView.h +// +// Created by Bradley Austin Davis 2015/04/25 +// Copyright 2015 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 +// + +#include "InfoView.h" + +#include +#include +#include +#include +const QUrl InfoView::QML{ "InfoView.qml" }; +const QString InfoView::NAME{ "InfoView" }; + +Setting::Handle infoVersion("info-version", QString()); + +InfoView::InfoView(QQuickItem* parent) : QQuickItem(parent) { + +} + +void InfoView::registerType() { + qmlRegisterType("Hifi", 1, 0, NAME.toLocal8Bit().constData()); +} + +QString fetchVersion(const QUrl& url) { + QXmlQuery query; + query.bindVariable("file", QVariant(url)); + query.setQuery("string((doc($file)//input[@id='version'])[1]/@value)"); + QString r; + query.evaluateTo(&r); + return r.trimmed(); +} + +void InfoView::show(const QString& path, bool firstOrChangedOnly) { + static bool registered{ false }; + if (!registered) { + registerType(); + registered = true; + } + QUrl url; + if (QDir(path).isRelative()) { + url = QUrl::fromLocalFile(PathUtils::resourcesPath() + path); + } else { + url = QUrl::fromLocalFile(path); + } + if (firstOrChangedOnly) { + const QString lastVersion = infoVersion.get(); + // If we have version information stored + if (lastVersion != QString::null) { + // Check to see the document version. If it's valid and matches + // the stored version, we're done, so exit + const QString version = fetchVersion(url); + if (version == QString::null || version == lastVersion) { + return; + } + } + } + auto offscreenUi = DependencyManager::get(); + QString infoViewName(NAME + "_" + path); + offscreenUi->show(QML, NAME + "_" + path, [=](QQmlContext* context, QObject* newObject){ + QQuickItem* item = dynamic_cast(newObject); + item->setWidth(720); + item->setHeight(720); + InfoView* newInfoView = newObject->findChild(); + Q_ASSERT(newInfoView); + newInfoView->parent()->setObjectName(infoViewName); + newInfoView->setUrl(url); + }); +} + +QUrl InfoView::url() { + return _url; +} + +void InfoView::setUrl(const QUrl& url) { + if (url != _url) { + _url = url; + emit urlChanged(); + } +} + diff --git a/libraries/ui/src/InfoView.h b/libraries/ui/src/InfoView.h new file mode 100644 index 0000000000..275effbfa5 --- /dev/null +++ b/libraries/ui/src/InfoView.h @@ -0,0 +1,38 @@ +// +// InfoView.h +// +// Created by Bradley Austin Davis 2015/04/25 +// Copyright 2015 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 +// + +#ifndef hifi_InfoView_h +#define hifi_InfoView_h + +#include +#include "OffscreenUi.h" + +class InfoView : public QQuickItem { + Q_OBJECT + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) + + static const QUrl QML; + static const QString NAME; +public: + static void registerType(); + static void show(const QString& path, bool firstOrChangedOnly = false); + + InfoView(QQuickItem* parent = nullptr); + QUrl url(); + void setUrl(const QUrl& url); + +signals: + void urlChanged(); + +private: + QUrl _url; +}; + +#endif // hifi_InfoView_h diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index d9c7cd890d..9b32aca96f 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -254,8 +254,11 @@ void OffscreenUi::updateQuick() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _renderControl->render(); - - Q_ASSERT(!glGetError()); + // FIXME The web browsers seem to be leaving GL in an error state. + // Need a debug context with sync logging to figure out why. + // for now just clear the errors + glGetError(); +// Q_ASSERT(!glGetError()); _quickWindow->resetOpenGLState(); diff --git a/tests/ui/src/main.cpp b/tests/ui/src/main.cpp index 24ef1a9cf3..19070e9699 100644 --- a/tests/ui/src/main.cpp +++ b/tests/ui/src/main.cpp @@ -27,15 +27,15 @@ #include #include #include - +#include #include #include #include #include #include - #include "MessageDialog.h" #include "VrMenu.h" +#include "InfoView.h" #include class RateCounter { @@ -241,12 +241,21 @@ public: } }; -const QString& getQmlDir() { +const QString& getResourcesDir() { static QString dir; if (dir.isEmpty()) { QDir path(__FILE__); path.cdUp(); - dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/")) + "/"; + dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/")) + "/"; + qDebug() << "Resources Path: " << dir; + } + return dir; +} + +const QString& getQmlDir() { + static QString dir; + if (dir.isEmpty()) { + dir = getResourcesDir() + "qml/"; qDebug() << "Qml Path: " << dir; } return dir; @@ -323,6 +332,7 @@ public: MessageDialog::registerType(); VrMenu::registerType(); + InfoView::registerType(); qmlRegisterType("Hifi", 1, 0, "MenuConstants"); @@ -412,24 +422,31 @@ protected: void keyPressEvent(QKeyEvent* event) { _altPressed = Qt::Key_Alt == event->key(); switch (event->key()) { - case Qt::Key_L: - if (event->modifiers() & Qt::CTRL) { - } - break; - case Qt::Key_K: - if (event->modifiers() & Qt::CTRL) { - OffscreenUi::question("Message title", "Message contents", [](QMessageBox::Button b){ - qDebug() << b; - }); - } - break; - case Qt::Key_J: - if (event->modifiers() & Qt::CTRL) { - auto offscreenUi = DependencyManager::get(); - rootMenu = offscreenUi->getRootItem()->findChild("rootMenu"); - QMetaObject::invokeMethod(rootMenu, "popup"); - } - break; + case Qt::Key_B: + if (event->modifiers() & Qt::CTRL) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->load("Browser.qml"); + } + break; + case Qt::Key_L: + if (event->modifiers() & Qt::CTRL) { + InfoView::show(getResourcesDir() + "html/interface-welcome.html", true); + } + break; + case Qt::Key_K: + if (event->modifiers() & Qt::CTRL) { + OffscreenUi::question("Message title", "Message contents", [](QMessageBox::Button b){ + qDebug() << b; + }); + } + break; + case Qt::Key_J: + if (event->modifiers() & Qt::CTRL) { + auto offscreenUi = DependencyManager::get(); + rootMenu = offscreenUi->getRootItem()->findChild("rootMenu"); + QMetaObject::invokeMethod(rootMenu, "popup"); + } + break; } QWindow::keyPressEvent(event); } @@ -445,7 +462,7 @@ protected: if (devicePixelRatio() != oldPixelRatio) { oldPixelRatio = devicePixelRatio(); resizeWindow(size()); - } + } QWindow::moveEvent(event); } };