mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 19:12:28 +02:00
Merge pull request #9990 from hyperlogic/bug-fix/sliders
Added inputMode property to Web3DOverlay
This commit is contained in:
commit
9e675d4c93
7 changed files with 309 additions and 31 deletions
|
@ -237,10 +237,7 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(qApp->getOverlays().getOverlay(selfOverlayID));
|
||||
auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) {
|
||||
auto self = weakSelf.lock();
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
if (overlayID == selfOverlayID) {
|
||||
if (self && overlayID == selfOverlayID) {
|
||||
self->handlePointerEvent(event);
|
||||
}
|
||||
};
|
||||
|
@ -254,22 +251,9 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
if (self->_pressed && overlayID == selfOverlayID) {
|
||||
// If the user mouses off the overlay while the button is down, simulate a touch end.
|
||||
QTouchEvent::TouchPoint point;
|
||||
point.setId(event.getID());
|
||||
point.setState(Qt::TouchPointReleased);
|
||||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi);
|
||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||
point.setScenePos(windowPoint);
|
||||
point.setPos(windowPoint);
|
||||
QList<QTouchEvent::TouchPoint> touchPoints;
|
||||
touchPoints.push_back(point);
|
||||
QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased,
|
||||
touchPoints);
|
||||
touchEvent->setWindow(self->_webSurface->getWindow());
|
||||
touchEvent->setDevice(&_touchDevice);
|
||||
touchEvent->setTarget(self->_webSurface->getRootItem());
|
||||
QCoreApplication::postEvent(self->_webSurface->getWindow(), touchEvent);
|
||||
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
||||
forwardPointerEvent(overlayID, event);
|
||||
}
|
||||
}, Qt::DirectConnection);
|
||||
|
||||
|
@ -346,6 +330,14 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) {
|
|||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
||||
if (_inputMode == Touch) {
|
||||
handlePointerEventAsTouch(event);
|
||||
} else {
|
||||
handlePointerEventAsMouse(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||
if (!_webSurface) {
|
||||
return;
|
||||
}
|
||||
|
@ -353,16 +345,16 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
|||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi);
|
||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||
|
||||
if (event.getType() == PointerEvent::Move) {
|
||||
if (event.getButtons() == PointerEvent::NoButtons && event.getType() == PointerEvent::Move) {
|
||||
// Forward a mouse move event to the Web surface.
|
||||
QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton,
|
||||
Qt::NoButton, Qt::NoModifier);
|
||||
QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
|
||||
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getType() == PointerEvent::Press) {
|
||||
if (event.getType() == PointerEvent::Press && event.getButton() == PointerEvent::PrimaryButton) {
|
||||
this->_pressed = true;
|
||||
} else if (event.getType() == PointerEvent::Release) {
|
||||
} else if (event.getType() == PointerEvent::Release && event.getButton() == PointerEvent::PrimaryButton) {
|
||||
this->_pressed = false;
|
||||
}
|
||||
|
||||
|
@ -401,6 +393,47 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
|||
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
|
||||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) {
|
||||
if (!_webSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi);
|
||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||
|
||||
if (event.getType() == PointerEvent::Press) {
|
||||
this->_pressed = true;
|
||||
} else if (event.getType() == PointerEvent::Release) {
|
||||
this->_pressed = false;
|
||||
}
|
||||
|
||||
Qt::MouseButtons buttons = Qt::NoButton;
|
||||
if (event.getButtons() & PointerEvent::PrimaryButton) {
|
||||
buttons |= Qt::LeftButton;
|
||||
}
|
||||
|
||||
QEvent::Type type;
|
||||
Qt::MouseButton button = Qt::NoButton;
|
||||
if (event.getButton() == PointerEvent::PrimaryButton) {
|
||||
button = Qt::LeftButton;
|
||||
}
|
||||
switch (event.getType()) {
|
||||
case PointerEvent::Press:
|
||||
type = QEvent::MouseButtonPress;
|
||||
break;
|
||||
case PointerEvent::Release:
|
||||
type = QEvent::MouseButtonRelease;
|
||||
break;
|
||||
case PointerEvent::Move:
|
||||
default:
|
||||
type = QEvent::MouseMove;
|
||||
break;
|
||||
}
|
||||
|
||||
QMouseEvent* mouseEvent = new QMouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier);
|
||||
QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent);
|
||||
}
|
||||
|
||||
void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
|
@ -443,6 +476,16 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
if (showKeyboardFocusHighlight.isValid()) {
|
||||
_showKeyboardFocusHighlight = showKeyboardFocusHighlight.toBool();
|
||||
}
|
||||
|
||||
auto inputModeValue = properties["inputMode"];
|
||||
if (inputModeValue.isValid()) {
|
||||
QString inputModeStr = inputModeValue.toString();
|
||||
if (inputModeStr == "Mouse") {
|
||||
_inputMode = Mouse;
|
||||
} else {
|
||||
_inputMode = Touch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant Web3DOverlay::getProperty(const QString& property) {
|
||||
|
@ -464,6 +507,14 @@ QVariant Web3DOverlay::getProperty(const QString& property) {
|
|||
if (property == "showKeyboardFocusHighlight") {
|
||||
return _showKeyboardFocusHighlight;
|
||||
}
|
||||
|
||||
if (property == "inputMode") {
|
||||
if (_inputMode == Mouse) {
|
||||
return QVariant("Mouse");
|
||||
} else {
|
||||
return QVariant("Touch");
|
||||
}
|
||||
}
|
||||
return Billboard3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
QObject* getEventHandler();
|
||||
void setProxyWindow(QWindow* proxyWindow);
|
||||
void handlePointerEvent(const PointerEvent& event);
|
||||
void handlePointerEventAsTouch(const PointerEvent& event);
|
||||
void handlePointerEventAsMouse(const PointerEvent& event);
|
||||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
|
@ -55,6 +57,11 @@ public:
|
|||
|
||||
virtual Web3DOverlay* createClone() const override;
|
||||
|
||||
enum InputMode {
|
||||
Touch,
|
||||
Mouse
|
||||
};
|
||||
|
||||
public slots:
|
||||
void emitScriptEvent(const QVariant& scriptMessage);
|
||||
|
||||
|
@ -63,6 +70,7 @@ signals:
|
|||
void webEventReceived(const QVariant& message);
|
||||
|
||||
private:
|
||||
InputMode _inputMode { Touch };
|
||||
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
||||
QMetaObject::Connection _connection;
|
||||
gpu::TexturePointer _texture;
|
||||
|
|
|
@ -143,7 +143,7 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve
|
|||
}
|
||||
|
||||
QScriptValue id = object.property("id");
|
||||
event._id = type.isNumber() ? (uint32_t)type.toNumber() : 0;
|
||||
event._id = id.isNumber() ? (uint32_t)id.toNumber() : 0;
|
||||
|
||||
glm::vec2 pos2D;
|
||||
vec2FromScriptValue(object.property("pos2D"), event._pos2D);
|
||||
|
@ -158,7 +158,8 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve
|
|||
vec3FromScriptValue(object.property("direction"), event._direction);
|
||||
|
||||
QScriptValue button = object.property("button");
|
||||
QString buttonStr = type.isString() ? type.toString() : "NoButtons";
|
||||
QString buttonStr = type.isString() ? button.toString() : "NoButtons";
|
||||
|
||||
if (buttonStr == "Primary") {
|
||||
event._button = PrimaryButton;
|
||||
} else if (buttonStr == "Secondary") {
|
||||
|
@ -186,3 +187,26 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve
|
|||
event._keyboardModifiers = (Qt::KeyboardModifiers)(object.property("keyboardModifiers").toUInt32());
|
||||
}
|
||||
}
|
||||
|
||||
static const char* typeToStringMap[PointerEvent::NumEventTypes] = { "Press", "DoublePress", "Release", "Move" };
|
||||
static const char* buttonsToStringMap[8] = {
|
||||
"NoButtons",
|
||||
"PrimaryButton",
|
||||
"SecondaryButton",
|
||||
"PrimaryButton | SecondaryButton",
|
||||
"TertiaryButton",
|
||||
"PrimaryButton | TertiaryButton",
|
||||
"SecondaryButton | TertiaryButton",
|
||||
"PrimaryButton | SecondaryButton | TertiaryButton",
|
||||
};
|
||||
|
||||
QDebug& operator<<(QDebug& dbg, const PointerEvent& p) {
|
||||
dbg.nospace() << "PointerEvent, type = " << typeToStringMap[p.getType()] << ", id = " << p.getID();
|
||||
dbg.nospace() << ", pos2D = (" << p.getPos2D().x << ", " << p.getPos2D().y;
|
||||
dbg.nospace() << "), pos3D = (" << p.getPos3D().x << ", " << p.getPos3D().y << ", " << p.getPos3D().z;
|
||||
dbg.nospace() << "), normal = (" << p.getNormal().x << ", " << p.getNormal().y << ", " << p.getNormal().z;
|
||||
dbg.nospace() << "), dir = (" << p.getDirection().x << ", " << p.getDirection().y << ", " << p.getDirection().z;
|
||||
dbg.nospace() << "), button = " << buttonsToStringMap[p.getButton()] << " " << (int)p.getButton();
|
||||
dbg.nospace() << ", buttons = " << buttonsToStringMap[p.getButtons()];
|
||||
return dbg;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
Press, // A button has just been pressed
|
||||
DoublePress, // A button has just been double pressed
|
||||
Release, // A button has just been released
|
||||
Move // The pointer has just moved
|
||||
Move, // The pointer has just moved
|
||||
NumEventTypes
|
||||
};
|
||||
|
||||
PointerEvent();
|
||||
|
@ -68,6 +69,8 @@ private:
|
|||
Qt::KeyboardModifiers _keyboardModifiers; // set of keys held when event was generated
|
||||
};
|
||||
|
||||
QDebug& operator<<(QDebug& dbg, const PointerEvent& p);
|
||||
|
||||
Q_DECLARE_METATYPE(PointerEvent)
|
||||
|
||||
#endif // hifi_PointerEvent_h
|
||||
|
|
157
scripts/developer/tests/sliderTest.html
Normal file
157
scripts/developer/tests/sliderTest.html
Normal file
|
@ -0,0 +1,157 @@
|
|||
<!--
|
||||
// quick_start_template.html
|
||||
//
|
||||
// Created by Faye Li on 3 Feb 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Slider Test</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600,700"" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
|
||||
<!-- <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" /> -->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
color: white;
|
||||
background: linear-gradient(#2b2b2b, #0f212e);
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: 90px;
|
||||
background: linear-gradient(#2b2b2b, #1e1e1e);
|
||||
font-weight: bold;
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
width: 480px;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 90px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
font-family: 'Raleway';
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
height: 28px;
|
||||
min-width: 120px;
|
||||
padding: 0px 18px;
|
||||
margin-right: 6px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
background: linear-gradient(#343434 20%, #000 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=button].red {
|
||||
color: #fff;
|
||||
background-color: #94132e;
|
||||
background: linear-gradient(#d42043 20%, #94132e 100%);
|
||||
}
|
||||
input[type=button].blue {
|
||||
color: #fff;
|
||||
background-color: #1080b8;
|
||||
background: linear-gradient(#00b4ef 20%, #1080b8 100%);
|
||||
}
|
||||
input[type=button].white {
|
||||
color: #121212;
|
||||
background-color: #afafaf;
|
||||
background: linear-gradient(#fff 20%, #afafaf 100%);
|
||||
}
|
||||
|
||||
input[type=button]:enabled:hover {
|
||||
background: linear-gradient(#000, #000);
|
||||
border: none;
|
||||
}
|
||||
input[type=button].red:enabled:hover {
|
||||
background: linear-gradient(#d42043, #d42043);
|
||||
border: none;
|
||||
}
|
||||
input[type=button].blue:enabled:hover {
|
||||
background: linear-gradient(#00b4ef, #00b4ef);
|
||||
border: none;
|
||||
}
|
||||
input[type=button].white:enabled:hover {
|
||||
background: linear-gradient(#fff, #fff);
|
||||
border: none;
|
||||
}
|
||||
|
||||
input[type=button]:active {
|
||||
background: linear-gradient(#343434, #343434);
|
||||
}
|
||||
input[type=button].red:active {
|
||||
background: linear-gradient(#94132e, #94132e);
|
||||
}
|
||||
input[type=button].blue:active {
|
||||
background: linear-gradient(#1080b8, #1080b8);
|
||||
}
|
||||
input[type=button].white:active {
|
||||
background: linear-gradient(#afafaf, #afafaf);
|
||||
}
|
||||
|
||||
input[type=button]:disabled {
|
||||
color: #252525;
|
||||
background: linear-gradient(#575757 20%, #252525 100%);
|
||||
}
|
||||
|
||||
input[type=button][pressed=pressed] {
|
||||
color: #00b4ef;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<h4>Slider Test</h4>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Native Input Range Slider</p>
|
||||
<p>
|
||||
<input type="range" name="native-slider" id="native-slider" value="60" min="0" max="100">
|
||||
</p>
|
||||
<p>Bootstrap Slider</p>
|
||||
<p>
|
||||
<input
|
||||
id="bootstrap-slider"
|
||||
type="text"
|
||||
data-provide="slider"
|
||||
data-slider-min="0"
|
||||
data-slider-max="100"
|
||||
data-slider-step="1"
|
||||
data-slider-value="60"
|
||||
data-slider-tooltip="hide"
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
|
||||
<script>
|
||||
function main() {
|
||||
console.log("ready");
|
||||
}
|
||||
|
||||
$(document).ready(main);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
35
scripts/developer/tests/sliderTestMain.js
Normal file
35
scripts/developer/tests/sliderTestMain.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
(function () {
|
||||
var HTML_URL = Script.resolvePath("sliderTest.html");
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var button = tablet.addButton({
|
||||
text: "SLIDER"
|
||||
});
|
||||
|
||||
function onClicked() {
|
||||
tablet.gotoWebScreen(HTML_URL);
|
||||
}
|
||||
|
||||
button.clicked.connect(onClicked);
|
||||
|
||||
var onSliderTestScreen = false;
|
||||
function onScreenChanged(type, url) {
|
||||
if (type === "Web" && url === HTML_URL) {
|
||||
// when switching to the slider page, change inputMode to "Mouse", this should make the sliders work.
|
||||
onSliderTestScreen = true;
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { inputMode: "Mouse" });
|
||||
} else if (onSliderTestScreen) {
|
||||
// when switching off of the slider page, change inputMode to back to "Touch".
|
||||
onSliderTestScreen = false;
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { inputMode: "Touch" });
|
||||
}
|
||||
}
|
||||
|
||||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
function cleanup() {
|
||||
tablet.removeButton(button);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
}());
|
|
@ -3467,7 +3467,7 @@ function MyController(hand) {
|
|||
if (intersectInfo) {
|
||||
var pointerEvent = {
|
||||
type: "Press",
|
||||
id: HARDWARE_MOUSE_ID,
|
||||
id: this.hand + 1,
|
||||
pos2D: projectOntoOverlayXYPlane(this.grabbedOverlay, intersectInfo.point),
|
||||
pos3D: intersectInfo.point,
|
||||
normal: intersectInfo.normal,
|
||||
|
@ -3516,7 +3516,7 @@ function MyController(hand) {
|
|||
if (this.deadspotExpired) {
|
||||
pointerEvent = {
|
||||
type: "Release",
|
||||
id: HARDWARE_MOUSE_ID,
|
||||
id: this.hand + 1,
|
||||
pos2D: pos2D,
|
||||
pos3D: pos3D,
|
||||
normal: intersectInfo.normal,
|
||||
|
@ -3560,7 +3560,7 @@ function MyController(hand) {
|
|||
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: HARDWARE_MOUSE_ID,
|
||||
id: this.hand + 1,
|
||||
pos2D: pos2D,
|
||||
pos3D: pos3D,
|
||||
normal: intersectInfo.normal,
|
||||
|
|
Loading…
Reference in a new issue