mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 22:36:57 +02:00
Improving toggle visibility and loading behavior
This commit is contained in:
parent
4b73481604
commit
16efa2a46f
12 changed files with 231 additions and 98 deletions
|
@ -5,16 +5,21 @@ import QtQuick.Window 2.2
|
||||||
import QtQuick.Controls.Styles 1.3
|
import QtQuick.Controls.Styles 1.3
|
||||||
|
|
||||||
CustomDialog {
|
CustomDialog {
|
||||||
id: dialog
|
|
||||||
title: "Go to..."
|
title: "Go to..."
|
||||||
objectName: "AddressBarDialog"
|
objectName: "AddressBarDialog"
|
||||||
SystemPalette { id: myPalette; colorGroup: SystemPalette.Active }
|
|
||||||
height: 128
|
height: 128
|
||||||
width: 512
|
width: 512
|
||||||
|
destroyOnCloseButton: false
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
reset();
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnabledChanged: {
|
||||||
|
if (enabled) {
|
||||||
|
addressLine.forceActiveFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ Item {
|
||||||
height: 256
|
height: 256
|
||||||
scale: 0.0
|
scale: 0.0
|
||||||
enabled: false
|
enabled: false
|
||||||
visible: false
|
property int animationDuration: 400
|
||||||
|
property bool destroyOnInvisible: false
|
||||||
|
property bool destroyOnCloseButton: true
|
||||||
|
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
scale = enabled ? 1.0 : 0.0
|
scale = enabled ? 1.0 : 0.0
|
||||||
|
@ -22,14 +24,24 @@ Item {
|
||||||
visible = (scale != 0.0);
|
visible = (scale != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
onVisibleChanged: {
|
||||||
scale = 1.0
|
if (!visible && destroyOnInvisible) {
|
||||||
|
console.log("Destroying closed component");
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (destroyOnCloseButton) {
|
||||||
|
destroyOnInvisible = true
|
||||||
|
}
|
||||||
|
enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
//This specifies how long the animation takes
|
//This specifies how long the animation takes
|
||||||
duration: 400
|
duration: dialog.animationDuration
|
||||||
//This selects an easing curve to interpolate with, the default is Easing.Linear
|
//This selects an easing curve to interpolate with, the default is Easing.Linear
|
||||||
easing.type: Easing.InOutBounce
|
easing.type: Easing.InOutBounce
|
||||||
}
|
}
|
||||||
|
@ -81,8 +93,8 @@ Item {
|
||||||
target: dialog
|
target: dialog
|
||||||
minimumX: 0
|
minimumX: 0
|
||||||
minimumY: 0
|
minimumY: 0
|
||||||
maximumX: dialog.parent.width - dialog.width
|
maximumX: dialog.parent ? dialog.parent.width - dialog.width : 0
|
||||||
maximumY: dialog.parent.height - dialog.height
|
maximumY: dialog.parent ? dialog.parent.height - dialog.height : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Image {
|
Image {
|
||||||
|
@ -97,7 +109,7 @@ Item {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
dialog.destroy()
|
dialog.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@ CustomDialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onEnabledChanged: {
|
||||||
|
if (enabled) {
|
||||||
|
username.forceActiveFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
username.text = ""
|
username.text = ""
|
||||||
password.text = ""
|
password.text = ""
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
|
import Hifi 1.0
|
||||||
import QtQuick 2.3
|
import QtQuick 2.3
|
||||||
import "componentCreation.js" as Creator
|
|
||||||
|
|
||||||
|
Root {
|
||||||
Item {
|
|
||||||
id: root
|
id: root
|
||||||
width: 1280
|
width: 1280
|
||||||
height: 720
|
height: 720
|
||||||
|
|
||||||
function loadChild(url) {
|
|
||||||
Creator.createObject(root, url)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,19 @@ import QtQuick.Dialogs 1.2
|
||||||
import QtQuick.Controls.Styles 1.3
|
import QtQuick.Controls.Styles 1.3
|
||||||
|
|
||||||
CustomDialog {
|
CustomDialog {
|
||||||
title: "Test Dlg"
|
title: "Test Dialog"
|
||||||
id: testDialog
|
id: testDialog
|
||||||
objectName: "TestDialog"
|
objectName: "TestDialog"
|
||||||
width: 512
|
width: 512
|
||||||
height: 512
|
height: 512
|
||||||
|
animationDuration: 200
|
||||||
|
|
||||||
|
onEnabledChanged: {
|
||||||
|
if (enabled) {
|
||||||
|
edit.forceActiveFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: clientArea
|
id: clientArea
|
||||||
// The client area
|
// The client area
|
||||||
|
@ -31,6 +38,7 @@ CustomDialog {
|
||||||
|
|
||||||
|
|
||||||
CustomTextEdit {
|
CustomTextEdit {
|
||||||
|
id: edit
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 12
|
anchors.leftMargin: 12
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
@ -1,25 +1,34 @@
|
||||||
|
import Hifi 1.0
|
||||||
import QtQuick 2.3
|
import QtQuick 2.3
|
||||||
import "componentCreation.js" as Creator
|
|
||||||
|
|
||||||
|
Root {
|
||||||
Item {
|
|
||||||
id: root
|
id: root
|
||||||
width: 1280
|
width: 1280
|
||||||
height: 720
|
height: 720
|
||||||
|
|
||||||
function loadChild(url) {
|
CustomButton {
|
||||||
Creator.createObject(root, url)
|
id: messageBox
|
||||||
|
anchors.right: createDialog.left
|
||||||
|
anchors.rightMargin: 24
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 24
|
||||||
|
text: "Message"
|
||||||
|
onClicked: {
|
||||||
|
console.log("Foo")
|
||||||
|
root.information("a")
|
||||||
|
console.log("Bar")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CustomButton {
|
CustomButton {
|
||||||
|
id: createDialog
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 24
|
anchors.rightMargin: 24
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: 24
|
anchors.bottomMargin: 24
|
||||||
text: "Test"
|
text: "Create"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
loadChild("TestDialog.qml");
|
root.loadChild("TestDialog.qml");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,12 @@ function finishCreation() {
|
||||||
// Error Handling
|
// Error Handling
|
||||||
console.log("Error creating object");
|
console.log("Error creating object");
|
||||||
} else {
|
} else {
|
||||||
instance.focus = true;
|
instance.enabled = true
|
||||||
}
|
}
|
||||||
} else if (component.status == Component.Error) {
|
} else if (component.status == Component.Error) {
|
||||||
// Error Handling
|
// Error Handling
|
||||||
console.log("Error loading component:", component.errorString());
|
console.log("Error loading component:", component.errorString());
|
||||||
|
} else {
|
||||||
|
console.log("Unknown component status: " + component.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -754,8 +754,8 @@ void Application::initializeUi() {
|
||||||
offscreenUi->create(_glWidget->context()->contextHandle());
|
offscreenUi->create(_glWidget->context()->contextHandle());
|
||||||
offscreenUi->resize(_glWidget->size());
|
offscreenUi->resize(_glWidget->size());
|
||||||
offscreenUi->setProxyWindow(_window->windowHandle());
|
offscreenUi->setProxyWindow(_window->windowHandle());
|
||||||
auto rootQml = PathUtils::resourcesPath() + "qml/Root.qml";
|
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||||
offscreenUi->loadQml(QUrl::fromLocalFile(rootQml));
|
offscreenUi->load("Root.qml");
|
||||||
offscreenUi->setMouseTranslator([this](const QPointF& p){
|
offscreenUi->setMouseTranslator([this](const QPointF& p){
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p));
|
glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p));
|
||||||
|
|
|
@ -35,14 +35,13 @@ void AddressBarDialog::loadAddress(const QString & address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO port to a QML based message box
|
|
||||||
void AddressBarDialog::displayAddressOfflineMessage() {
|
void AddressBarDialog::displayAddressOfflineMessage() {
|
||||||
QMessageBox::information(nullptr, "Address offline",
|
OffscreenUi::information("Address offline",
|
||||||
"That user or place is currently offline.");
|
"That user or place is currently offline.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO port to a QML based message box
|
|
||||||
void AddressBarDialog::displayAddressNotFoundMessage() {
|
void AddressBarDialog::displayAddressNotFoundMessage() {
|
||||||
QMessageBox::information(nullptr, "Address not found",
|
OffscreenUi::information("Address not found",
|
||||||
"There is no address information for that user or place.");
|
"There is no address information for that user or place.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,29 @@
|
||||||
#include <QOpenGLFramebufferObject>
|
#include <QOpenGLFramebufferObject>
|
||||||
#include <QOpenGLDebugLogger>
|
#include <QOpenGLDebugLogger>
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
|
#include <QtQml>
|
||||||
|
|
||||||
|
class OffscreenUiRoot : public QQuickItem {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
OffscreenUiRoot(QQuickItem *parent = 0);
|
||||||
|
Q_INVOKABLE void information(const QString & title, const QString & text);
|
||||||
|
Q_INVOKABLE void loadChild(const QUrl & url) {
|
||||||
|
DependencyManager::get<OffscreenUi>()->load(url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OffscreenUiRoot::OffscreenUiRoot(QQuickItem *parent) : QQuickItem(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUiRoot::information(const QString & title, const QString & text = "foo") {
|
||||||
|
OffscreenUi::information(title, text);
|
||||||
|
}
|
||||||
|
|
||||||
OffscreenUi::OffscreenUi() {
|
OffscreenUi::OffscreenUi() {
|
||||||
|
::qmlRegisterType<OffscreenUiRoot>("Hifi", 1, 0, "Root");
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenUi::~OffscreenUi() {
|
OffscreenUi::~OffscreenUi() {
|
||||||
|
@ -62,19 +83,18 @@ void OffscreenUi::create(QOpenGLContext * shareContext) {
|
||||||
// is needed too).
|
// is needed too).
|
||||||
connect(_renderControl, &QQuickRenderControl::renderRequested, this, &OffscreenUi::requestRender);
|
connect(_renderControl, &QQuickRenderControl::renderRequested, this, &OffscreenUi::requestRender);
|
||||||
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, &OffscreenUi::requestUpdate);
|
connect(_renderControl, &QQuickRenderControl::sceneChanged, this, &OffscreenUi::requestUpdate);
|
||||||
connect(_quickWindow, &QQuickWindow::focusObjectChanged, this, [this](QObject *object){
|
|
||||||
OffscreenUi * p = this;
|
|
||||||
qDebug() << "Focus changed to " << object;
|
|
||||||
});
|
|
||||||
_quickWindow->focusObject();
|
_quickWindow->focusObject();
|
||||||
|
|
||||||
_qmlComponent = new QQmlComponent(_qmlEngine);
|
_qmlComponent = new QQmlComponent(_qmlEngine);
|
||||||
|
|
||||||
// Initialize the render control and our OpenGL resources.
|
// Initialize the render control and our OpenGL resources.
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
_renderControl->initialize(&_context);
|
_renderControl->initialize(&_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::addImportPath(const QString & path) {
|
||||||
|
_qmlEngine->addImportPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
void OffscreenUi::resize(const QSize & newSize) {
|
void OffscreenUi::resize(const QSize & newSize) {
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
|
|
||||||
|
@ -102,10 +122,15 @@ QQmlContext * OffscreenUi::qmlContext() {
|
||||||
return QQmlEngine::contextForObject(_rootItem);
|
return QQmlEngine::contextForObject(_rootItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenUi::loadQml(const QUrl & qmlSource, std::function<void(QQmlContext*)> f) {
|
void OffscreenUi::setBaseUrl(const QUrl & baseUrl) {
|
||||||
|
_qmlEngine->setBaseUrl(baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::load(const QUrl & qmlSource, std::function<void(QQmlContext*)> f) {
|
||||||
|
qDebug() << "Loading QML from URL " << qmlSource;
|
||||||
_qmlComponent->loadUrl(qmlSource);
|
_qmlComponent->loadUrl(qmlSource);
|
||||||
if (_qmlComponent->isLoading())
|
if (_qmlComponent->isLoading())
|
||||||
connect(_qmlComponent, &QQmlComponent::statusChanged, this, &OffscreenUi::finishQmlLoad);
|
connect(_qmlComponent, &QQmlComponent::statusChanged, this, [] {});
|
||||||
else
|
else
|
||||||
finishQmlLoad();
|
finishQmlLoad();
|
||||||
}
|
}
|
||||||
|
@ -131,30 +156,43 @@ void OffscreenUi::finishQmlLoad() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject *rootObject = _qmlComponent->create();
|
QObject *newObject = _qmlComponent->create();
|
||||||
if (_qmlComponent->isError()) {
|
if (_qmlComponent->isError()) {
|
||||||
QList<QQmlError> errorList = _qmlComponent->errors();
|
QList<QQmlError> errorList = _qmlComponent->errors();
|
||||||
foreach(const QQmlError &error, errorList)
|
foreach(const QQmlError &error, errorList)
|
||||||
qWarning() << error.url() << error.line() << error;
|
qWarning() << error.url() << error.line() << error;
|
||||||
qFatal("Unable to finish loading QML");
|
if (!_rootItem) {
|
||||||
|
qFatal("Unable to finish loading QML root");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rootItem = qobject_cast<QQuickItem *>(rootObject);
|
QQuickItem * newItem = qobject_cast<QQuickItem *>(newObject);
|
||||||
if (!_rootItem) {
|
if (!newItem) {
|
||||||
qWarning("run: Not a QQuickItem");
|
qWarning("run: Not a QQuickItem");
|
||||||
delete rootObject;
|
delete newObject;
|
||||||
qFatal("Unable to find root QQuickItem");
|
if (!_rootItem) {
|
||||||
|
qFatal("Unable to find root QQuickItem");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can assign focus to the root item (critical for
|
// Make sure we make items focusable (critical for
|
||||||
// supporting keyboard shortcuts)
|
// supporting keyboard shortcuts)
|
||||||
_rootItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||||
// The root item is ready. Associate it with the window.
|
|
||||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
if (!_rootItem) {
|
||||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
// The root item is ready. Associate it with the window.
|
||||||
qDebug() << "Finished setting up QML provider";
|
_rootItem = newItem;
|
||||||
|
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||||
|
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||||
|
} else {
|
||||||
|
// Allow child windows to be destroyed from JS
|
||||||
|
QQmlEngine::setObjectOwnership(newItem, QQmlEngine::JavaScriptOwnership);
|
||||||
|
newItem->setParent(_rootItem);
|
||||||
|
newItem->setParentItem(_rootItem);
|
||||||
|
newItem->setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -240,7 +278,7 @@ bool OffscreenUi::eventFilter(QObject * dest, QEvent * e) {
|
||||||
case QEvent::KeyRelease:
|
case QEvent::KeyRelease:
|
||||||
{
|
{
|
||||||
e->ignore();
|
e->ignore();
|
||||||
if (QApplication::sendEvent(_quickWindow, e)) {
|
if (QCoreApplication::sendEvent(_quickWindow, e)) {
|
||||||
return e->isAccepted();
|
return e->isAccepted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,38 +340,55 @@ void OffscreenUi::setProxyWindow(QWindow * window) {
|
||||||
|
|
||||||
void OffscreenUi::show(const QUrl & url, const QString & name) {
|
void OffscreenUi::show(const QUrl & url, const QString & name) {
|
||||||
QQuickItem * item = _rootItem->findChild<QQuickItem*>(name);
|
QQuickItem * item = _rootItem->findChild<QQuickItem*>(name);
|
||||||
|
// First load?
|
||||||
if (nullptr == item) {
|
if (nullptr == item) {
|
||||||
load(url);
|
load(url);
|
||||||
item = _rootItem->findChild<QQuickItem*>(name);
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr != item) {
|
|
||||||
item->setEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
item->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenUi::toggle(const QUrl & url, const QString & name) {
|
void OffscreenUi::toggle(const QUrl & url, const QString & name) {
|
||||||
QQuickItem * item = _rootItem->findChild<QQuickItem*>(name);
|
QQuickItem * item = _rootItem->findChild<QQuickItem*>(name);
|
||||||
// First load?
|
// First load?
|
||||||
if (nullptr == item) {
|
if (nullptr == item) {
|
||||||
show(url, name);
|
load(url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
item->setEnabled(!item->isEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle the visibity AND the enabled flag (otherwise invisible
|
void OffscreenUi::messageBox(const QString &title, const QString &text,
|
||||||
// dialogs can still swallow keyboard input)
|
QMessageBox::Icon icon,
|
||||||
bool newFlag = !item->isEnabled();
|
QMessageBox::StandardButtons buttons,
|
||||||
item->setEnabled(newFlag);
|
ButtonCallback f) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::information(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons,
|
||||||
|
ButtonCallback callback) {
|
||||||
|
callback(QMessageBox::information(nullptr, title, text, buttons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::question(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons,
|
||||||
|
ButtonCallback callback) {
|
||||||
|
callback(QMessageBox::question(nullptr, title, text, buttons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::warning(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons,
|
||||||
|
ButtonCallback callback) {
|
||||||
|
callback(QMessageBox::warning(nullptr, title, text, buttons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::critical(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons,
|
||||||
|
ButtonCallback callback) {
|
||||||
|
callback(QMessageBox::critical(nullptr, title, text, buttons));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OffscreenUi::load(const QUrl & url) {
|
OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {};
|
||||||
qDebug() << "Loading from url: " << url;
|
|
||||||
QVariant returnedValue;
|
|
||||||
QVariant msg = url;
|
|
||||||
QMetaObject::invokeMethod(_rootItem, "loadChild",
|
|
||||||
Q_RETURN_ARG(QVariant, returnedValue),
|
|
||||||
Q_ARG(QVariant, msg));
|
|
||||||
qDebug() << "QML function returned:" << returnedValue.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#include "OffscreenUi.moc"
|
|
@ -12,26 +12,25 @@
|
||||||
#ifndef hifi_OffscreenUi_h
|
#ifndef hifi_OffscreenUi_h
|
||||||
#define hifi_OffscreenUi_h
|
#define hifi_OffscreenUi_h
|
||||||
|
|
||||||
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QOffscreenSurface>
|
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QQuickRenderControl>
|
#include <QQuickRenderControl>
|
||||||
#include <QQuickImageProvider>
|
#include <QQuickImageProvider>
|
||||||
#include <GLMHelpers.h>
|
|
||||||
#include <ThreadHelpers.h>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QApplication>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
#include <ThreadHelpers.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
#include "FboCache.h"
|
|
||||||
#include "OffscreenGlCanvas.h"
|
#include "OffscreenGlCanvas.h"
|
||||||
|
#include "FboCache.h"
|
||||||
|
#include <QQuickItem>
|
||||||
|
|
||||||
|
|
||||||
class OffscreenUi : public OffscreenGlCanvas, public Dependency {
|
class OffscreenUi : public OffscreenGlCanvas, public Dependency {
|
||||||
|
@ -60,11 +59,14 @@ public:
|
||||||
virtual ~OffscreenUi();
|
virtual ~OffscreenUi();
|
||||||
void create(QOpenGLContext * context);
|
void create(QOpenGLContext * context);
|
||||||
void resize(const QSize & size);
|
void resize(const QSize & size);
|
||||||
void loadQml(const QUrl & qmlSource, std::function<void(QQmlContext*)> f = [](QQmlContext*) {});
|
void load(const QUrl & qmlSource, std::function<void(QQmlContext*)> f = [](QQmlContext*) {});
|
||||||
void load(const QUrl & url);
|
void load(const QString & qmlSourceFile, std::function<void(QQmlContext*)> f = [](QQmlContext*) {}) {
|
||||||
|
load(QUrl(qmlSourceFile), f);
|
||||||
|
}
|
||||||
void show(const QUrl & url, const QString & name);
|
void show(const QUrl & url, const QString & name);
|
||||||
void toggle(const QUrl & url, const QString & name);
|
void toggle(const QUrl & url, const QString & name);
|
||||||
|
void setBaseUrl(const QUrl & baseUrl);
|
||||||
|
void addImportPath(const QString & path);
|
||||||
QQmlContext * qmlContext();
|
QQmlContext * qmlContext();
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
|
@ -77,6 +79,32 @@ public:
|
||||||
_mouseTranslator = mt;
|
_mouseTranslator = mt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Messagebox replacement functions
|
||||||
|
using ButtonCallback = std::function < void(QMessageBox::StandardButton) >;
|
||||||
|
static ButtonCallback NO_OP_CALLBACK;
|
||||||
|
|
||||||
|
static void messageBox(const QString &title, const QString &text,
|
||||||
|
QMessageBox::Icon icon,
|
||||||
|
QMessageBox::StandardButtons buttons,
|
||||||
|
ButtonCallback f);
|
||||||
|
|
||||||
|
static void information(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||||
|
ButtonCallback callback = NO_OP_CALLBACK);
|
||||||
|
|
||||||
|
static void question(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
|
||||||
|
ButtonCallback callback = [](QMessageBox::StandardButton) {});
|
||||||
|
|
||||||
|
static void warning(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||||
|
ButtonCallback callback = [](QMessageBox::StandardButton) {});
|
||||||
|
|
||||||
|
static void critical(const QString &title, const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||||
|
ButtonCallback callback = [](QMessageBox::StandardButton) {});
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -69,6 +69,17 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const QString & getQmlDir() {
|
||||||
|
static QString dir;
|
||||||
|
if (dir.isEmpty()) {
|
||||||
|
QDir path(__FILE__);
|
||||||
|
path.cdUp();
|
||||||
|
dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/")) + "/";
|
||||||
|
qDebug() << "Qml Path: " << dir;
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
// Create a simple OpenGL window that renders text in various ways
|
// Create a simple OpenGL window that renders text in various ways
|
||||||
class QTestWindow : public QWindow {
|
class QTestWindow : public QWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -77,7 +88,6 @@ class QTestWindow : public QWindow {
|
||||||
QSize _size;
|
QSize _size;
|
||||||
TextRenderer* _textRenderer[4];
|
TextRenderer* _textRenderer[4];
|
||||||
RateCounter fps;
|
RateCounter fps;
|
||||||
OffscreenUi _offscreenUi;
|
|
||||||
int testQmlTexture{ 0 };
|
int testQmlTexture{ 0 };
|
||||||
//ProgramPtr _planeProgam;
|
//ProgramPtr _planeProgam;
|
||||||
//ShapeWrapperPtr _planeShape;
|
//ShapeWrapperPtr _planeShape;
|
||||||
|
@ -90,11 +100,12 @@ protected:
|
||||||
private:
|
private:
|
||||||
void resizeWindow(const QSize & size) {
|
void resizeWindow(const QSize & size) {
|
||||||
_size = size;
|
_size = size;
|
||||||
_offscreenUi.resize(_size);
|
DependencyManager::get<OffscreenUi>()->resize(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QTestWindow() {
|
QTestWindow() {
|
||||||
|
DependencyManager::set<OffscreenUi>();
|
||||||
setSurfaceType(QSurface::OpenGLSurface);
|
setSurfaceType(QSurface::OpenGLSurface);
|
||||||
|
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
|
@ -154,30 +165,30 @@ public:
|
||||||
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
_offscreenUi.create(_context);
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
offscreenUi->create(_context);
|
||||||
// FIXME, need to switch to a QWindow for mouse and keyboard input to work
|
// FIXME, need to switch to a QWindow for mouse and keyboard input to work
|
||||||
_offscreenUi.setProxyWindow(this);
|
offscreenUi->setProxyWindow(this);
|
||||||
// "#0e7077"
|
// "#0e7077"
|
||||||
setFramePosition(QPoint(-1000, 0));
|
setFramePosition(QPoint(-1000, 0));
|
||||||
resize(QSize(800, 600));
|
resize(QSize(800, 600));
|
||||||
|
|
||||||
QApplication::applicationDirPath();
|
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
|
||||||
QDir path(__FILE__);
|
offscreenUi->load(QUrl("TestRoot.qml"));
|
||||||
path.cdUp();
|
offscreenUi->addImportPath(getQmlDir());
|
||||||
static const QString f(path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/TestRoot.qml")));
|
offscreenUi->addImportPath(".");
|
||||||
|
|
||||||
_offscreenUi.loadQml(QUrl::fromLocalFile(f));
|
connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [this, offscreenUi](int textureId) {
|
||||||
connect(&_offscreenUi, &OffscreenUi::textureUpdated, this, [&](int textureId) {
|
offscreenUi->lockTexture(textureId);
|
||||||
_offscreenUi.lockTexture(textureId);
|
|
||||||
assert(!glGetError());
|
assert(!glGetError());
|
||||||
GLuint oldTexture = testQmlTexture;
|
GLuint oldTexture = testQmlTexture;
|
||||||
testQmlTexture = textureId;
|
testQmlTexture = textureId;
|
||||||
if (oldTexture) {
|
if (oldTexture) {
|
||||||
_offscreenUi.releaseTexture(oldTexture);
|
offscreenUi->releaseTexture(oldTexture);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
installEventFilter(&_offscreenUi);
|
installEventFilter(offscreenUi.data());
|
||||||
_offscreenUi.resume();
|
offscreenUi->resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~QTestWindow() {
|
virtual ~QTestWindow() {
|
||||||
|
@ -197,8 +208,10 @@ protected:
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent *event) {
|
void keyPressEvent(QKeyEvent *event) {
|
||||||
switch (event->key()) {
|
switch (event->key()) {
|
||||||
case Qt::Key_Slash:
|
case Qt::Key_L:
|
||||||
_offscreenUi.toggle(QString("TestDialog.qml"), "TestDialog");
|
if (event->modifiers() & Qt::CTRL) {
|
||||||
|
DependencyManager::get<OffscreenUi>()->toggle(QString("TestDialog.qml"), "TestDialog");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QWindow::keyPressEvent(event);
|
QWindow::keyPressEvent(event);
|
||||||
|
@ -319,6 +332,7 @@ int main(int argc, char** argv) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
//QLoggingCategory::setFilterRules("qt.quick.mouse.debug = true");
|
//QLoggingCategory::setFilterRules("qt.quick.mouse.debug = true");
|
||||||
QTestWindow window;
|
QTestWindow window;
|
||||||
|
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
timer.setInterval(1);
|
timer.setInterval(1);
|
||||||
app.connect(&timer, &QTimer::timeout, &app, [&] {
|
app.connect(&timer, &QTimer::timeout, &app, [&] {
|
||||||
|
|
Loading…
Reference in a new issue