Merge pull request #9418 from druiz17/tabletController

game controller input with tablet
This commit is contained in:
Seth Alves 2017-01-18 09:31:56 -08:00 committed by GitHub
commit 439d6f0fa3
10 changed files with 237 additions and 26 deletions

View file

@ -4,9 +4,10 @@ import QtGraphicalEffects 1.0
Item { Item {
id: tablet id: tablet
objectName: "tablet" objectName: "tablet"
property double micLevel: 0.8 property double micLevel: 0.8
property int rowIndex: 0
property int columnIndex: 0
property int count: (flowMain.children.length - 1)
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -42,7 +43,6 @@ Item {
// pass a reference to the tabletRoot object to the button. // pass a reference to the tabletRoot object to the button.
button.tabletRoot = parent.parent; button.tabletRoot = parent.parent;
return button; 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();
} }

View file

@ -109,6 +109,7 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
enabled: true
onClicked: { onClicked: {
console.log("Tablet Button Clicked!"); console.log("Tablet Button Clicked!");
if (tabletButton.inDebugMode) { if (tabletButton.inDebugMode) {

View file

@ -5,7 +5,7 @@ import QtQml 2.2
import "." import "."
import "../../styles-uit" import "../../styles-uit"
Item { FocusScope {
id: tabletMenu id: tabletMenu
objectName: "tabletMenu" objectName: "tabletMenu"
@ -87,6 +87,10 @@ Item {
} }
} }
function pop() {
menuPopperUpper.closeLastMenu();
}
function setRootMenu(menu) { function setRootMenu(menu) {
tabletMenu.rootMenu = menu tabletMenu.rootMenu = menu
buildMenu() buildMenu()

View file

@ -13,12 +13,12 @@ import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import "../../styles-uit" import "../../styles-uit"
import "."
FocusScope { FocusScope {
id: root id: root
implicitHeight: background.height implicitHeight: background.height
implicitWidth: background.width implicitWidth: background.width
objectName: "root"
property alias currentItem: listView.currentItem property alias currentItem: listView.currentItem
property alias model: listView.model property alias model: listView.model
property bool isSubMenu: false property bool isSubMenu: false
@ -45,6 +45,7 @@ FocusScope {
height: 720 height: 720
contentWidth: 480 contentWidth: 480
contentHeight: 720 contentHeight: 720
objectName: "menuList"
topMargin: hifi.dimensions.menuPadding.y topMargin: hifi.dimensions.menuPadding.y
bottomMargin: hifi.dimensions.menuPadding.y bottomMargin: hifi.dimensions.menuPadding.y
@ -107,17 +108,21 @@ FocusScope {
} }
currentIndex = originalIndex; 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.onUpPressed: previousItem();
Keys.onDownPressed: nextItem(); Keys.onDownPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem(); Keys.onSpacePressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem(); Keys.onRightPressed: selectCurrentItem();
Keys.onReturnPressed: 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(); }
} }

View file

@ -58,7 +58,6 @@ Item {
for (var i = 0; i < items.length; ++i) { for (var i = 0; i < items.length; ++i) {
var item = items[i]; var item = items[i];
if (!item.visible) continue; if (!item.visible) continue;
console.log(item.title)
switch (item.type) { switch (item.type) {
case MenuItemType.Menu: case MenuItemType.Menu:
result.append({"name": item.title, "item": item}) result.append({"name": item.title, "item": item})
@ -81,6 +80,7 @@ Item {
if (menuStack.length) { if (menuStack.length) {
topMenu = menuStack[menuStack.length - 1]; topMenu = menuStack[menuStack.length - 1];
topMenu.focus = true; topMenu.focus = true;
topMenu.forceActiveFocus();
// show current menu level on nav bar // show current menu level on nav bar
if (topMenu.objectName === "") { if (topMenu.objectName === "") {
breadcrumbText.text = "Menu"; breadcrumbText.text = "Menu";
@ -90,8 +90,7 @@ Item {
} else { } else {
breadcrumbText.text = "Menu"; breadcrumbText.text = "Menu";
topMenu = null; topMenu = null;
//offscreenFlags.navigationFocused = false; offscreenFlags.navigationFocused = false;
menuRoot.enabled = false;
} }
} }
@ -99,7 +98,8 @@ Item {
menuStack.push(newMenu); menuStack.push(newMenu);
topMenu = newMenu; topMenu = newMenu;
topMenu.focus = true; topMenu.focus = true;
//offscreenFlags.navigationFocused = true; topMenu.forceActiveFocus();
offscreenFlags.navigationFocused = true;
} }
function clearMenus() { function clearMenus() {
@ -159,16 +159,20 @@ Item {
function popup(parent, items) { function popup(parent, items) {
d.clearMenus(); d.clearMenus();
menuRoot.enabled = true;
d.buildMenu(items, point); d.buildMenu(items, point);
} }
function closeLastMenu() { function closeLastMenu() {
if (d.menuStack.length) { if (d.menuStack.length > 1) {
d.popMenu(); d.popMenu();
return true; return true;
} }
return false; return false;
} }
function previousItem() { d.topMenu.previousItem(); }
function nextItem() { d.topMenu.nextItem(); }
function selectCurrentItem() { d.topMenu.selectCurrentItem(); }
function previousPage() { d.topMenu.previousPage(); }
} }

View file

@ -6,6 +6,8 @@ Item {
objectName: "tabletRoot" objectName: "tabletRoot"
property var eventBridge; property var eventBridge;
signal showDesktop();
function loadSource(url) { function loadSource(url) {
loader.source = url; loader.source = url;
} }
@ -33,7 +35,6 @@ Item {
height: parent.height height: parent.height
onLoaded: { onLoaded: {
// propogate eventBridge to WebEngineView
if (loader.item.hasOwnProperty("eventBridge")) { if (loader.item.hasOwnProperty("eventBridge")) {
loader.item.eventBridge = eventBridge; loader.item.eventBridge = eventBridge;
@ -44,8 +45,12 @@ Item {
} }
}); });
} }
loader.item.forceActiveFocus();
offscreenFlags.navigationFocused = true;
} }
} }
Component.onDestruction: { offscreenFlags.navigationFocused = false; }
width: 480 width: 480
height: 720 height: 720

View file

@ -977,6 +977,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) {
using namespace controller; using namespace controller;
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
if (offscreenUi->navigationFocused()) { if (offscreenUi->navigationFocused()) {
auto actionEnum = static_cast<Action>(action); auto actionEnum = static_cast<Action>(action);
int key = Qt::Key_unknown; int key = Qt::Key_unknown;
@ -1021,25 +1022,28 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
break; break;
} }
if (navAxis) { auto window = tabletScriptingInterface->getTabletWindow();
if (navAxis && window) {
if (lastKey != Qt::Key_unknown) { if (lastKey != Qt::Key_unknown) {
QKeyEvent event(QEvent::KeyRelease, lastKey, Qt::NoModifier); QKeyEvent event(QEvent::KeyRelease, lastKey, Qt::NoModifier);
sendEvent(offscreenUi->getWindow(), &event); sendEvent(window, &event);
lastKey = Qt::Key_unknown; lastKey = Qt::Key_unknown;
} }
if (key != Qt::Key_unknown) { if (key != Qt::Key_unknown) {
QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier); QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier);
sendEvent(offscreenUi->getWindow(), &event); sendEvent(window, &event);
tabletScriptingInterface->processEvent(&event);
lastKey = key; lastKey = key;
} }
} else if (key != Qt::Key_unknown) { } else if (key != Qt::Key_unknown && window) {
if (state) { if (state) {
QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier); QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier);
sendEvent(offscreenUi->getWindow(), &event); sendEvent(window, &event);
tabletScriptingInterface->processEvent(&event);
} else { } else {
QKeyEvent event(QEvent::KeyRelease, key, Qt::NoModifier); QKeyEvent event(QEvent::KeyRelease, key, Qt::NoModifier);
sendEvent(offscreenUi->getWindow(), &event); sendEvent(window, &event);
} }
return; return;
} }

View file

@ -151,6 +151,8 @@ void Web3DOverlay::loadSourceURL() {
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); 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()); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());
} }
} }

View file

@ -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 // TabletProxy
// //
@ -200,6 +283,10 @@ void TabletProxy::addButtonsToHomeScreen() {
QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
} }
QObject* TabletProxy::getTabletSurface() {
return _qmlOffscreenSurface;
}
void TabletProxy::addButtonsToMenuScreen() { void TabletProxy::addButtonsToMenuScreen() {
if (!_qmlTabletRoot) { if (!_qmlTabletRoot) {
return; return;
@ -212,7 +299,6 @@ void TabletProxy::addButtonsToMenuScreen() {
QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu"); QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu");
if (!VrMenu) { if (!VrMenu) {
qDebug() << "----------> could not find vr menu";
return; return;
} }
@ -246,6 +332,28 @@ QQuickItem* TabletProxy::getQmlTablet() const {
return tablet; 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 // TabletButtonProxy
// //

View file

@ -47,6 +47,16 @@ public:
void setQmlTabletRoot(QString tabletId, QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface); 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: protected:
std::mutex _mutex; std::mutex _mutex;
std::map<QString, QSharedPointer<TabletProxy>> _tabletProxies; std::map<QString, QSharedPointer<TabletProxy>> _tabletProxies;
@ -112,6 +122,13 @@ public:
*/ */
Q_INVOKABLE void emitScriptEvent(QVariant msg); Q_INVOKABLE void emitScriptEvent(QVariant msg);
QObject* getTabletSurface();
QQuickItem* getQmlTablet() const;
QQuickItem* getQmlMenu() const;
signals: signals:
/**jsdoc /**jsdoc
* Signaled when this tablet receives an event from the html/js embedded in the tablet * Signaled when this tablet receives an event from the html/js embedded in the tablet
@ -126,7 +143,6 @@ private slots:
void addButtonsToMenuScreen(); void addButtonsToMenuScreen();
protected: protected:
void removeButtonsFromHomeScreen(); void removeButtonsFromHomeScreen();
QQuickItem* getQmlTablet() const;
QString _name; QString _name;
std::mutex _mutex; std::mutex _mutex;