mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge pull request #9418 from druiz17/tabletController
game controller input with tablet
This commit is contained in:
commit
439d6f0fa3
10 changed files with 237 additions and 26 deletions
|
@ -4,9 +4,10 @@ import QtGraphicalEffects 1.0
|
|||
Item {
|
||||
id: tablet
|
||||
objectName: "tablet"
|
||||
|
||||
property double micLevel: 0.8
|
||||
|
||||
property int rowIndex: 0
|
||||
property int columnIndex: 0
|
||||
property int count: (flowMain.children.length - 1)
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
|
@ -42,7 +43,6 @@ Item {
|
|||
|
||||
// pass a reference to the tabletRoot object to the button.
|
||||
button.tabletRoot = parent.parent;
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
|
@ -212,5 +212,67 @@ Item {
|
|||
}
|
||||
}
|
||||
]
|
||||
|
||||
function setCurrentItemState(state) {
|
||||
var index = rowIndex + columnIndex;
|
||||
|
||||
if (index >= 0 && index <= count ) {
|
||||
flowMain.children[index].state = state;
|
||||
}
|
||||
}
|
||||
function nextItem() {
|
||||
setCurrentItemState("base state");
|
||||
var nextColumnIndex = (columnIndex + 3 + 1) % 3;
|
||||
var nextIndex = rowIndex + nextColumnIndex;
|
||||
if(nextIndex <= count) {
|
||||
columnIndex = nextColumnIndex;
|
||||
};
|
||||
setCurrentItemState("hover state");
|
||||
}
|
||||
|
||||
function previousItem() {
|
||||
setCurrentItemState("base state");
|
||||
var prevIndex = (columnIndex + 3 - 1) % 3;
|
||||
if((rowIndex + prevIndex) <= count){
|
||||
columnIndex = prevIndex;
|
||||
}
|
||||
setCurrentItemState("hover state");
|
||||
}
|
||||
|
||||
function upItem() {
|
||||
setCurrentItemState("base state");
|
||||
rowIndex = rowIndex - 3;
|
||||
if (rowIndex < 0 ) {
|
||||
rowIndex = (count - (count % 3));
|
||||
var index = rowIndex + columnIndex;
|
||||
if(index > count) {
|
||||
rowIndex = rowIndex - 3;
|
||||
}
|
||||
}
|
||||
setCurrentItemState("hover state");
|
||||
}
|
||||
|
||||
function downItem() {
|
||||
setCurrentItemState("base state");
|
||||
rowIndex = rowIndex + 3;
|
||||
var index = rowIndex + columnIndex;
|
||||
if (index > count ) {
|
||||
rowIndex = 0;
|
||||
}
|
||||
setCurrentItemState("hover state");
|
||||
}
|
||||
|
||||
function selectItem() {
|
||||
flowMain.children[rowIndex + columnIndex].clicked();
|
||||
if (tabletRoot) {
|
||||
tabletRoot.playButtonClickSound();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onRightPressed: nextItem();
|
||||
Keys.onLeftPressed: previousItem();
|
||||
Keys.onDownPressed: downItem();
|
||||
Keys.onUpPressed: upItem();
|
||||
Keys.onReturnPressed: selectItem();
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
onClicked: {
|
||||
console.log("Tablet Button Clicked!");
|
||||
if (tabletButton.inDebugMode) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import QtQml 2.2
|
|||
import "."
|
||||
import "../../styles-uit"
|
||||
|
||||
Item {
|
||||
FocusScope {
|
||||
id: tabletMenu
|
||||
objectName: "tabletMenu"
|
||||
|
||||
|
@ -87,6 +87,10 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
function pop() {
|
||||
menuPopperUpper.closeLastMenu();
|
||||
}
|
||||
|
||||
function setRootMenu(menu) {
|
||||
tabletMenu.rootMenu = menu
|
||||
buildMenu()
|
||||
|
|
|
@ -13,12 +13,12 @@ import QtQuick.Controls 1.4
|
|||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../../styles-uit"
|
||||
|
||||
import "."
|
||||
FocusScope {
|
||||
id: root
|
||||
implicitHeight: background.height
|
||||
implicitWidth: background.width
|
||||
|
||||
objectName: "root"
|
||||
property alias currentItem: listView.currentItem
|
||||
property alias model: listView.model
|
||||
property bool isSubMenu: false
|
||||
|
@ -45,6 +45,7 @@ FocusScope {
|
|||
height: 720
|
||||
contentWidth: 480
|
||||
contentHeight: 720
|
||||
objectName: "menuList"
|
||||
|
||||
topMargin: hifi.dimensions.menuPadding.y
|
||||
bottomMargin: hifi.dimensions.menuPadding.y
|
||||
|
@ -107,17 +108,21 @@ FocusScope {
|
|||
}
|
||||
currentIndex = originalIndex;
|
||||
}
|
||||
|
||||
function previousItem() { currentIndex = (currentIndex + count - 1) % count; }
|
||||
function nextItem() { currentIndex = (currentIndex + count + 1) % count; }
|
||||
function selectCurrentItem() { if (currentIndex != -1) root.selected(currentItem.source); }
|
||||
|
||||
|
||||
Keys.onUpPressed: previousItem();
|
||||
Keys.onDownPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
Keys.onLeftPressed: previousPage();
|
||||
}
|
||||
|
||||
function previousItem() { listView.currentIndex = (listView.currentIndex + listView.count - 1) % listView.count; }
|
||||
function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; }
|
||||
function selectCurrentItem() { if (listView.currentIndex != -1) root.selected(currentItem.source); }
|
||||
function previousPage() { root.parent.pop(); }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ Item {
|
|||
for (var i = 0; i < items.length; ++i) {
|
||||
var item = items[i];
|
||||
if (!item.visible) continue;
|
||||
console.log(item.title)
|
||||
switch (item.type) {
|
||||
case MenuItemType.Menu:
|
||||
result.append({"name": item.title, "item": item})
|
||||
|
@ -81,6 +80,7 @@ Item {
|
|||
if (menuStack.length) {
|
||||
topMenu = menuStack[menuStack.length - 1];
|
||||
topMenu.focus = true;
|
||||
topMenu.forceActiveFocus();
|
||||
// show current menu level on nav bar
|
||||
if (topMenu.objectName === "") {
|
||||
breadcrumbText.text = "Menu";
|
||||
|
@ -90,8 +90,7 @@ Item {
|
|||
} else {
|
||||
breadcrumbText.text = "Menu";
|
||||
topMenu = null;
|
||||
//offscreenFlags.navigationFocused = false;
|
||||
menuRoot.enabled = false;
|
||||
offscreenFlags.navigationFocused = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +98,8 @@ Item {
|
|||
menuStack.push(newMenu);
|
||||
topMenu = newMenu;
|
||||
topMenu.focus = true;
|
||||
//offscreenFlags.navigationFocused = true;
|
||||
topMenu.forceActiveFocus();
|
||||
offscreenFlags.navigationFocused = true;
|
||||
}
|
||||
|
||||
function clearMenus() {
|
||||
|
@ -159,16 +159,20 @@ Item {
|
|||
|
||||
function popup(parent, items) {
|
||||
d.clearMenus();
|
||||
menuRoot.enabled = true;
|
||||
d.buildMenu(items, point);
|
||||
}
|
||||
|
||||
function closeLastMenu() {
|
||||
if (d.menuStack.length) {
|
||||
if (d.menuStack.length > 1) {
|
||||
d.popMenu();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function previousItem() { d.topMenu.previousItem(); }
|
||||
function nextItem() { d.topMenu.nextItem(); }
|
||||
function selectCurrentItem() { d.topMenu.selectCurrentItem(); }
|
||||
function previousPage() { d.topMenu.previousPage(); }
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ Item {
|
|||
objectName: "tabletRoot"
|
||||
property var eventBridge;
|
||||
|
||||
signal showDesktop();
|
||||
|
||||
function loadSource(url) {
|
||||
loader.source = url;
|
||||
}
|
||||
|
@ -33,7 +35,6 @@ Item {
|
|||
height: parent.height
|
||||
|
||||
onLoaded: {
|
||||
// propogate eventBridge to WebEngineView
|
||||
if (loader.item.hasOwnProperty("eventBridge")) {
|
||||
loader.item.eventBridge = eventBridge;
|
||||
|
||||
|
@ -44,8 +45,12 @@ Item {
|
|||
}
|
||||
});
|
||||
}
|
||||
loader.item.forceActiveFocus();
|
||||
offscreenFlags.navigationFocused = true;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: { offscreenFlags.navigationFocused = false; }
|
||||
|
||||
width: 480
|
||||
height: 720
|
||||
|
|
|
@ -977,6 +977,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) {
|
||||
using namespace controller;
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
if (offscreenUi->navigationFocused()) {
|
||||
auto actionEnum = static_cast<Action>(action);
|
||||
int key = Qt::Key_unknown;
|
||||
|
@ -1021,25 +1022,28 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
break;
|
||||
}
|
||||
|
||||
if (navAxis) {
|
||||
auto window = tabletScriptingInterface->getTabletWindow();
|
||||
if (navAxis && window) {
|
||||
if (lastKey != Qt::Key_unknown) {
|
||||
QKeyEvent event(QEvent::KeyRelease, lastKey, Qt::NoModifier);
|
||||
sendEvent(offscreenUi->getWindow(), &event);
|
||||
sendEvent(window, &event);
|
||||
lastKey = Qt::Key_unknown;
|
||||
}
|
||||
|
||||
if (key != Qt::Key_unknown) {
|
||||
QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier);
|
||||
sendEvent(offscreenUi->getWindow(), &event);
|
||||
sendEvent(window, &event);
|
||||
tabletScriptingInterface->processEvent(&event);
|
||||
lastKey = key;
|
||||
}
|
||||
} else if (key != Qt::Key_unknown) {
|
||||
} else if (key != Qt::Key_unknown && window) {
|
||||
if (state) {
|
||||
QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier);
|
||||
sendEvent(offscreenUi->getWindow(), &event);
|
||||
sendEvent(window, &event);
|
||||
tabletScriptingInterface->processEvent(&event);
|
||||
} else {
|
||||
QKeyEvent event(QEvent::KeyRelease, key, Qt::NoModifier);
|
||||
sendEvent(offscreenUi->getWindow(), &event);
|
||||
sendEvent(window, &event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,8 @@ void Web3DOverlay::loadSourceURL() {
|
|||
|
||||
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto flags = tabletScriptingInterface->getFlags();
|
||||
_webSurface->getRootContext()->setContextProperty("offscreenFlags", flags);
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,89 @@ void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qm
|
|||
}
|
||||
}
|
||||
|
||||
QQuickWindow* TabletScriptingInterface::getTabletWindow() {
|
||||
TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system"));
|
||||
QObject* qmlSurface = tablet->getTabletSurface();
|
||||
OffscreenQmlSurface* surface = dynamic_cast<OffscreenQmlSurface*>(qmlSurface);
|
||||
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
QQuickWindow* window = surface->getWindow();
|
||||
return window;
|
||||
}
|
||||
|
||||
void TabletScriptingInterface::processMenuEvents(QObject* object, const QKeyEvent* event) {
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Down:
|
||||
QMetaObject::invokeMethod(object, "nextItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
QMetaObject::invokeMethod(object, "previousItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
QMetaObject::invokeMethod(object, "previousPage");
|
||||
break;
|
||||
|
||||
case Qt::Key_Right:
|
||||
QMetaObject::invokeMethod(object, "selectCurrentItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Return:
|
||||
QMetaObject::invokeMethod(object, "selectCurrentItem");
|
||||
break;
|
||||
defualt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TabletScriptingInterface::processTabletEvents(QObject* object, const QKeyEvent* event) {
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Down:
|
||||
QMetaObject::invokeMethod(object, "downItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
QMetaObject::invokeMethod(object, "upItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
QMetaObject::invokeMethod(object, "previousItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Right:
|
||||
QMetaObject::invokeMethod(object, "nextItem");
|
||||
break;
|
||||
|
||||
case Qt::Key_Return:
|
||||
QMetaObject::invokeMethod(object, "selectItem");
|
||||
break;
|
||||
defualt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabletScriptingInterface::processEvent(const QKeyEvent* event) {
|
||||
TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system"));
|
||||
QObject* qmlTablet = tablet->getQmlTablet();
|
||||
QObject* qmlMenu = tablet->getQmlMenu();
|
||||
|
||||
if (qmlTablet) {
|
||||
processTabletEvents(qmlTablet, event);
|
||||
} else if (qmlMenu) {
|
||||
processMenuEvents(qmlMenu, event);
|
||||
}
|
||||
}
|
||||
|
||||
QObject* TabletScriptingInterface::getFlags()
|
||||
{
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
return offscreenUi->getFlags();
|
||||
}
|
||||
|
||||
//
|
||||
// TabletProxy
|
||||
//
|
||||
|
@ -200,6 +283,10 @@ void TabletProxy::addButtonsToHomeScreen() {
|
|||
QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
|
||||
}
|
||||
|
||||
QObject* TabletProxy::getTabletSurface() {
|
||||
return _qmlOffscreenSurface;
|
||||
}
|
||||
|
||||
void TabletProxy::addButtonsToMenuScreen() {
|
||||
if (!_qmlTabletRoot) {
|
||||
return;
|
||||
|
@ -212,7 +299,6 @@ void TabletProxy::addButtonsToMenuScreen() {
|
|||
|
||||
QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu");
|
||||
if (!VrMenu) {
|
||||
qDebug() << "----------> could not find vr menu";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -246,6 +332,28 @@ QQuickItem* TabletProxy::getQmlTablet() const {
|
|||
return tablet;
|
||||
}
|
||||
|
||||
QQuickItem* TabletProxy::getQmlMenu() const {
|
||||
if (!_qmlTabletRoot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
|
||||
if (!loader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu");
|
||||
if (!VrMenu) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QQuickItem* menuList = VrMenu->findChild<QQuickItem*>("tabletMenuHandlerItem");
|
||||
if (!menuList) {
|
||||
return nullptr;
|
||||
}
|
||||
return menuList;
|
||||
}
|
||||
|
||||
//
|
||||
// TabletButtonProxy
|
||||
//
|
||||
|
|
|
@ -47,6 +47,16 @@ public:
|
|||
|
||||
void setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface);
|
||||
|
||||
void processEvent(const QKeyEvent* event);
|
||||
|
||||
QQuickWindow* getTabletWindow();
|
||||
|
||||
QObject* getFlags();
|
||||
|
||||
private:
|
||||
void processMenuEvents(QObject* object, const QKeyEvent* event);
|
||||
void processTabletEvents(QObject* object, const QKeyEvent* event);
|
||||
|
||||
protected:
|
||||
std::mutex _mutex;
|
||||
std::map<QString, QSharedPointer<TabletProxy>> _tabletProxies;
|
||||
|
@ -112,6 +122,13 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void emitScriptEvent(QVariant msg);
|
||||
|
||||
|
||||
QObject* getTabletSurface();
|
||||
|
||||
QQuickItem* getQmlTablet() const;
|
||||
|
||||
QQuickItem* getQmlMenu() const;
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when this tablet receives an event from the html/js embedded in the tablet
|
||||
|
@ -126,7 +143,6 @@ private slots:
|
|||
void addButtonsToMenuScreen();
|
||||
protected:
|
||||
void removeButtonsFromHomeScreen();
|
||||
QQuickItem* getQmlTablet() const;
|
||||
|
||||
QString _name;
|
||||
std::mutex _mutex;
|
||||
|
|
Loading…
Reference in a new issue