mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 09:23:17 +02:00
Merge pull request #6758 from jherico/vr_keys
Allow keyboard navigation of the VR/overlay menu
This commit is contained in:
commit
26f0030ca0
4 changed files with 157 additions and 138 deletions
|
@ -49,7 +49,7 @@ VrDialog {
|
|||
|
||||
onUrlChanged: {
|
||||
var currentUrl = url.toString();
|
||||
var newUrl = urlHandler.fixupUrl(currentUrl);
|
||||
var newUrl = urlHandler.fixupUrl(currentUrl).toString();
|
||||
if (newUrl != currentUrl) {
|
||||
url = newUrl;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import Hifi 1.0 as Hifi
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
import "controls"
|
||||
import "styles"
|
||||
|
||||
|
@ -21,15 +23,12 @@ Hifi.VrMenu {
|
|||
property var models: []
|
||||
property var columns: []
|
||||
|
||||
|
||||
onEnabledChanged: {
|
||||
if (enabled && columns.length == 0) {
|
||||
pushColumn(rootMenu.items);
|
||||
}
|
||||
opacity = enabled ? 1.0 : 0.0
|
||||
if (enabled) {
|
||||
forceActiveFocus()
|
||||
}
|
||||
offscreenFlags.navigationFocused = enabled;
|
||||
}
|
||||
|
||||
// The actual animator
|
||||
|
@ -49,13 +48,12 @@ Hifi.VrMenu {
|
|||
}
|
||||
|
||||
property var menuBuilder: Component {
|
||||
Border {
|
||||
HifiConstants { id: hifi }
|
||||
property int menuDepth
|
||||
VrMenuView {
|
||||
property int menuDepth: root.models.length - 1
|
||||
model: root.models[menuDepth]
|
||||
|
||||
Component.onCompleted: {
|
||||
menuDepth = root.models.length - 1
|
||||
if (menuDepth == 0) {
|
||||
if (menuDepth === 0) {
|
||||
x = lastMousePosition.x - 20
|
||||
y = lastMousePosition.y - 20
|
||||
} else {
|
||||
|
@ -65,48 +63,8 @@ Hifi.VrMenu {
|
|||
}
|
||||
}
|
||||
|
||||
border.color: hifi.colors.hifiBlue
|
||||
color: hifi.colors.window
|
||||
implicitHeight: listView.implicitHeight + 16
|
||||
implicitWidth: listView.implicitWidth + 16
|
||||
|
||||
Column {
|
||||
id: listView
|
||||
property real minWidth: 0
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 8
|
||||
left: parent.left
|
||||
leftMargin: 8
|
||||
right: parent.right
|
||||
rightMargin: 8
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.models[menuDepth]
|
||||
delegate: Loader {
|
||||
id: loader
|
||||
source: "VrMenuItem.qml"
|
||||
Binding {
|
||||
target: loader.item
|
||||
property: "menuContainer"
|
||||
value: root
|
||||
when: loader.status == Loader.Ready
|
||||
}
|
||||
Binding {
|
||||
target: loader.item
|
||||
property: "source"
|
||||
value: modelData
|
||||
when: loader.status == Loader.Ready
|
||||
}
|
||||
Binding {
|
||||
target: loader.item
|
||||
property: "listView"
|
||||
value: listView
|
||||
when: loader.status == Loader.Ready
|
||||
}
|
||||
}
|
||||
}
|
||||
onSelected: {
|
||||
root.selectItem(menuDepth, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,14 +74,14 @@ Hifi.VrMenu {
|
|||
}
|
||||
|
||||
function pushColumn(items) {
|
||||
models.push(items)
|
||||
models.push(itemsToModel(items))
|
||||
if (columns.length) {
|
||||
var oldColumn = lastColumn();
|
||||
//oldColumn.enabled = false
|
||||
}
|
||||
var newColumn = menuBuilder.createObject(root);
|
||||
columns.push(newColumn);
|
||||
newColumn.forceActiveFocus();
|
||||
forceActiveFocus();
|
||||
}
|
||||
|
||||
function popColumn() {
|
||||
|
@ -145,13 +103,39 @@ Hifi.VrMenu {
|
|||
curColumn.forceActiveFocus();
|
||||
}
|
||||
|
||||
function selectItem(source) {
|
||||
function itemsToModel(items) {
|
||||
var newListModel = Qt.createQmlObject('import QtQuick 2.2; ListModel {}', root);
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
var item = items[i];
|
||||
switch (item.type) {
|
||||
case 2:
|
||||
newListModel.append({"type":item.type, "name": item.title, "item": item})
|
||||
break;
|
||||
case 1:
|
||||
newListModel.append({"type":item.type, "name": item.text, "item": item})
|
||||
break;
|
||||
case 0:
|
||||
newListModel.append({"type":item.type, "name": "-----", "item": item})
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newListModel;
|
||||
}
|
||||
|
||||
function selectItem(depth, source) {
|
||||
var popped = false;
|
||||
while (depth + 1 < columns.length) {
|
||||
popColumn()
|
||||
popped = true
|
||||
}
|
||||
|
||||
switch (source.type) {
|
||||
case 2:
|
||||
lastColumn().enabled = false
|
||||
pushColumn(source.items)
|
||||
break;
|
||||
case 1:
|
||||
source.trigger()
|
||||
if (!popped) source.trigger()
|
||||
enabled = false
|
||||
break;
|
||||
case 0:
|
||||
|
@ -165,14 +149,6 @@ Hifi.VrMenu {
|
|||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
root.popColumn()
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
id: mouseArea
|
||||
|
@ -206,4 +182,36 @@ Hifi.VrMenu {
|
|||
function removeItem(menu, menuItem) {
|
||||
menu.removeItem(menuItem);
|
||||
}
|
||||
|
||||
function previousItem() {
|
||||
if (columns.length) {
|
||||
lastColumn().incrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
|
||||
function nextItem() {
|
||||
if (columns.length) {
|
||||
lastColumn().decrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
|
||||
function selectCurrentItem() {
|
||||
if (columns.length) {
|
||||
var depth = columns.length - 1;
|
||||
var index = lastColumn().currentIndex;
|
||||
if (index >= 0) {
|
||||
var model = models[depth];
|
||||
var item = model.get(index).item;
|
||||
selectItem(depth, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onDownPressed: previousItem();
|
||||
Keys.onUpPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onLeftPressed: popColumn();
|
||||
Keys.onEscapePressed: popColumn();
|
||||
}
|
||||
|
|
|
@ -6,57 +6,18 @@ import "styles"
|
|||
|
||||
Item {
|
||||
id: root
|
||||
HifiConstants {
|
||||
id: hifi
|
||||
HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
||||
// The model object
|
||||
property alias text: label.text
|
||||
property var source
|
||||
property var menuContainer
|
||||
property var listView
|
||||
|
||||
MouseArea {
|
||||
anchors.left: parent.left
|
||||
anchors.right: tag.right
|
||||
anchors.rightMargin: -4
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
|
||||
Rectangle {
|
||||
id: highlight
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
color: "#7f0e7077"
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
//if (source.type == 2 && enabled) {
|
||||
// timer.start()
|
||||
//}
|
||||
highlight.visible = source.enabled
|
||||
}
|
||||
|
||||
onExited: {
|
||||
timer.stop()
|
||||
highlight.visible = false
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
select()
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: source.visible ? label.implicitHeight * 1.5 : 0
|
||||
implicitWidth: label.implicitWidth + label.height * 2.5
|
||||
implicitWidth: label.width + label.height * 2.5
|
||||
visible: source.visible
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 1000
|
||||
onTriggered: parent.select()
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
|
||||
FontAwesome {
|
||||
clip: true
|
||||
|
@ -84,32 +45,18 @@ Item {
|
|||
|
||||
Text {
|
||||
id: label
|
||||
text: typedText()
|
||||
anchors.left: check.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: source.enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
enabled: source.enabled && source.visible
|
||||
enabled: source.visible && (source.type !== 0 ? source.enabled : false)
|
||||
visible: source.visible
|
||||
function typedText() {
|
||||
if (source) {
|
||||
switch (source.type) {
|
||||
case 2:
|
||||
return source.title
|
||||
case 1:
|
||||
return source.text
|
||||
case 0:
|
||||
return "-----"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
FontAwesome {
|
||||
id: tag
|
||||
x: listView.width - width - 4
|
||||
x: root.parent.width - width
|
||||
size: label.height
|
||||
width: implicitWidth
|
||||
visible: source.visible && (source.type == 2)
|
||||
|
@ -117,17 +64,4 @@ Item {
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: label.color
|
||||
}
|
||||
|
||||
function select() {
|
||||
//timer.stop();
|
||||
var popped = false
|
||||
while (columns.length - 1 > listView.parent.menuDepth) {
|
||||
popColumn()
|
||||
popped = true
|
||||
}
|
||||
|
||||
if (!popped || source.type != 1) {
|
||||
root.menuContainer.selectItem(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
77
interface/resources/qml/VrMenuView.qml
Normal file
77
interface/resources/qml/VrMenuView.qml
Normal file
|
@ -0,0 +1,77 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
import "styles"
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
width: 128
|
||||
height: count * 32
|
||||
onEnabledChanged: recalcSize();
|
||||
onVisibleChanged: recalcSize();
|
||||
onCountChanged: recalcSize();
|
||||
|
||||
signal selected(var item)
|
||||
|
||||
highlight: Rectangle {
|
||||
width: root.currentItem ? root.currentItem.width : 0
|
||||
height: root.currentItem ? root.currentItem.height : 0
|
||||
color: "lightsteelblue"; radius: 3
|
||||
}
|
||||
|
||||
delegate: VrMenuItem {
|
||||
text: name
|
||||
source: item
|
||||
onImplicitHeightChanged: root.recalcSize()
|
||||
onImplicitWidthChanged: root.recalcSize()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: root.currentIndex = index
|
||||
onClicked: root.selected(item)
|
||||
}
|
||||
}
|
||||
|
||||
function recalcSize() {
|
||||
if (model.count !== count || !visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
var originalIndex = currentIndex;
|
||||
var maxWidth = width;
|
||||
var newHeight = 0;
|
||||
for (var i = 0; i < count; ++i) {
|
||||
currentIndex = i;
|
||||
if (!currentItem) {
|
||||
continue;
|
||||
}
|
||||
if (currentItem && currentItem.implicitWidth > maxWidth) {
|
||||
maxWidth = currentItem.implicitWidth
|
||||
}
|
||||
if (currentItem.visible) {
|
||||
newHeight += currentItem.implicitHeight
|
||||
}
|
||||
}
|
||||
if (maxWidth > width) {
|
||||
width = maxWidth;
|
||||
}
|
||||
if (newHeight > height) {
|
||||
height = newHeight
|
||||
}
|
||||
currentIndex = originalIndex;
|
||||
}
|
||||
|
||||
Border {
|
||||
id: border
|
||||
anchors.fill: parent
|
||||
anchors.margins: -8
|
||||
z: parent.z - 1
|
||||
border.color: hifi.colors.hifiBlue
|
||||
color: hifi.colors.window
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in a new issue