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 {
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();
}

View file

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

View file

@ -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()

View file

@ -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(); }
}

View file

@ -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(); }
}

View file

@ -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

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) {
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;
}

View file

@ -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());
}
}

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
//
@ -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
//

View file

@ -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;