mirror of
https://github.com/overte-org/overte.git
synced 2025-04-30 00:23:06 +02:00
handle repositioning of qml windows
This commit is contained in:
parent
d80bf58021
commit
04df84974c
7 changed files with 154 additions and 21 deletions
|
@ -4,7 +4,7 @@ import QtWebEngine 1.1
|
||||||
|
|
||||||
import "controls"
|
import "controls"
|
||||||
import "styles"
|
import "styles"
|
||||||
import "windows"
|
import "windows-uit"
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
|
|
|
@ -21,8 +21,29 @@ FocusScope {
|
||||||
objectName: "desktop"
|
objectName: "desktop"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
onHeightChanged: d.repositionAll();
|
property vector4d recommendedRect: vector4d(0,0,0,0);
|
||||||
onWidthChanged: d.repositionAll();
|
|
||||||
|
onHeightChanged: {
|
||||||
|
var oldRecommendedRect = recommendedRect;
|
||||||
|
var newRecommendedRectJS = Controller.getRecommendedOverlayRect();
|
||||||
|
var newRecommendedRect = Qt.vector4d(newRecommendedRectJS.x, newRecommendedRectJS.y, newRecommendedRectJS.z, newRecommendedRectJS.w);
|
||||||
|
if (oldRecommendedRect != Qt.vector4d(0,0,0,0)
|
||||||
|
&& oldRecommendedRect != newRecommendedRect) {
|
||||||
|
d.repositionAll();
|
||||||
|
}
|
||||||
|
recommendedRect = newRecommendedRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
onWidthChanged: {
|
||||||
|
var oldRecommendedRect = recommendedRect;
|
||||||
|
var newRecommendedRectJS = Controller.getRecommendedOverlayRect();
|
||||||
|
var newRecommendedRect = Qt.vector4d(newRecommendedRectJS.x, newRecommendedRectJS.y, newRecommendedRectJS.z, newRecommendedRectJS.w);
|
||||||
|
if (oldRecommendedRect != Qt.vector4d(0,0,0,0)
|
||||||
|
&& oldRecommendedRect != newRecommendedRect) {
|
||||||
|
d.repositionAll();
|
||||||
|
}
|
||||||
|
recommendedRect = newRecommendedRect;
|
||||||
|
}
|
||||||
|
|
||||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||||
// when they're opened.
|
// when they're opened.
|
||||||
|
@ -202,12 +223,23 @@ FocusScope {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAvatarInputsWindow() {
|
||||||
|
for (var i = 0; i < desktop.children.length; ++i) {
|
||||||
|
var child = desktop.children[i];
|
||||||
|
if (child.objectName === "AvatarInputs") {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function repositionAll() {
|
function repositionAll() {
|
||||||
var windows = d.getTopLevelWindows();
|
var windows = d.getTopLevelWindows();
|
||||||
for (var i = 0; i < windows.length; ++i) {
|
for (var i = 0; i < windows.length; ++i) {
|
||||||
reposition(windows[i]);
|
reposition(windows[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// also reposition the avatar inputs window if need be
|
||||||
|
repositionWindow(getAvatarInputsWindow(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,32 +270,62 @@ FocusScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
function reposition(item) {
|
function reposition(item) {
|
||||||
|
var targetWindow = d.getDesktopWindow(item);
|
||||||
|
repositionWindow(targetWindow, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function repositionWindow(targetWindow, forceReposition) {
|
||||||
if (desktop.width === 0 || desktop.height === 0) {
|
if (desktop.width === 0 || desktop.height === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetWindow = d.getDesktopWindow(item);
|
|
||||||
if (!targetWindow) {
|
if (!targetWindow) {
|
||||||
console.warn("Could not find top level window for " + item);
|
console.warn("Could not find top level window for " + item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var recommended = Controller.getRecommendedOverlayRect();
|
||||||
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
||||||
// If the window is completely offscreen, reposition it
|
|
||||||
if ((targetWindow.x > desktop.width || (targetWindow.x + targetWindow.width) < 0) ||
|
// if we asked to force reposition, or if the window is completely outside of the recommended rectangle, reposition it
|
||||||
(targetWindow.y > desktop.height || (targetWindow.y + targetWindow.height) < 0)) {
|
if (forceReposition || (targetWindow.x > recommended.z || (targetWindow.x + targetWindow.width) < recommended.x) ||
|
||||||
|
(targetWindow.y > recommended.w || (targetWindow.y + targetWindow.height) < recommended.y)) {
|
||||||
newPosition.x = -1
|
newPosition.x = -1
|
||||||
newPosition.y = -1
|
newPosition.y = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (newPosition.x === -1 && newPosition.y === -1) {
|
if (newPosition.x === -1 && newPosition.y === -1) {
|
||||||
// Set initial window position
|
// Set initial window position
|
||||||
// var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y);
|
// var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y);
|
||||||
// var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height);
|
// var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height);
|
||||||
// newPosition = Utils.clampVector(newPosition, minPosition, maxPosition);
|
// newPosition = Utils.clampVector(newPosition, minPosition, maxPosition);
|
||||||
// newPosition = Utils.randomPosition(minPosition, maxPosition);
|
// newPosition = Utils.randomPosition(minPosition, maxPosition);
|
||||||
newPosition = Qt.vector2d(desktop.width / 2 - targetWindow.width / 2,
|
|
||||||
desktop.height / 2 - targetWindow.height / 2);
|
// center in new space
|
||||||
|
//newPosition = Qt.vector2d(desktop.width / 2 - targetWindow.width / 2,
|
||||||
|
// desktop.height / 2 - targetWindow.height / 2);
|
||||||
|
|
||||||
|
var oldRecommendedRect = recommendedRect;
|
||||||
|
var oldRecommendedDimmensions = { x: oldRecommendedRect.z - oldRecommendedRect.x, y: oldRecommendedRect.w - oldRecommendedRect.y };
|
||||||
|
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||||
|
var newRecommendedDimmensions = { x: newRecommendedRect.z - newRecommendedRect.x, y: newRecommendedRect.w - newRecommendedRect.y };
|
||||||
|
|
||||||
|
var originRelativeX = (targetWindow.x - oldRecommendedRect.x);
|
||||||
|
var originRelativeY = (targetWindow.y - oldRecommendedRect.y);
|
||||||
|
if (isNaN(originRelativeX)) {
|
||||||
|
originRelativeX = 0;
|
||||||
|
}
|
||||||
|
if (isNaN(originRelativeY)) {
|
||||||
|
originRelativeY = 0;
|
||||||
|
}
|
||||||
|
var fractionX = Utils.clamp(originRelativeX / oldRecommendedDimmensions.x, 0, 1);
|
||||||
|
var fractionY = Utils.clamp(originRelativeY / oldRecommendedDimmensions.y, 0, 1);
|
||||||
|
|
||||||
|
var newX = (fractionX * newRecommendedDimmensions.x) + newRecommendedRect.x;
|
||||||
|
var newY = (fractionY * newRecommendedDimmensions.y) + newRecommendedRect.y;
|
||||||
|
|
||||||
|
newPosition = Qt.vector2d(newX, newY);
|
||||||
}
|
}
|
||||||
targetWindow.x = newPosition.x;
|
targetWindow.x = newPosition.x;
|
||||||
targetWindow.y = newPosition.y;
|
targetWindow.y = newPosition.y;
|
||||||
|
|
|
@ -2669,8 +2669,6 @@ void Application::idle(uint64_t now) {
|
||||||
_overlayConductor.setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Overlays));
|
_overlayConductor.setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Overlays));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
|
if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
|
||||||
|
@ -4882,24 +4880,42 @@ QRect Application::getRenderingGeometry() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::uvec2 Application::getUiSize() const {
|
glm::uvec2 Application::getUiSize() const {
|
||||||
return getActiveDisplayPlugin()->getRecommendedUiSize();
|
glm::uvec2 result;
|
||||||
|
if (_displayPlugin) {
|
||||||
|
result = getActiveDisplayPlugin()->getRecommendedUiSize();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::uvec4 Application::getRecommendedOverlayRect() const {
|
glm::uvec4 Application::getRecommendedOverlayRect() const {
|
||||||
return getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
glm::uvec4 result;
|
||||||
|
if (_displayPlugin) {
|
||||||
|
result = getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Application::getDeviceSize() const {
|
QSize Application::getDeviceSize() const {
|
||||||
return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
QSize result;
|
||||||
|
if (_displayPlugin) {
|
||||||
|
result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::isThrottleRendering() const {
|
bool Application::isThrottleRendering() const {
|
||||||
|
if (_displayPlugin) {
|
||||||
return getActiveDisplayPlugin()->isThrottled();
|
return getActiveDisplayPlugin()->isThrottled();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::hasFocus() const {
|
bool Application::hasFocus() const {
|
||||||
|
if (_displayPlugin) {
|
||||||
return getActiveDisplayPlugin()->hasFocus();
|
return getActiveDisplayPlugin()->hasFocus();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec2 Application::getViewportDimensions() const {
|
glm::vec2 Application::getViewportDimensions() const {
|
||||||
return toGlm(getDeviceSize());
|
return toGlm(getDeviceSize());
|
||||||
|
|
|
@ -80,9 +80,9 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
||||||
return qApp->getUiSize();
|
return qApp->getUiSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec4 ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||||
auto rect = qApp->getRecommendedOverlayRect();
|
auto rect = qApp->getRecommendedOverlayRect();
|
||||||
return vec4(rect.x, rect.y, rect.z, rect.w);
|
return vec4toVariant(vec4(rect.x, rect.y, rect.z, rect.w));
|
||||||
}
|
}
|
||||||
|
|
||||||
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ public slots:
|
||||||
virtual void releaseJoystick(int joystickIndex);
|
virtual void releaseJoystick(int joystickIndex);
|
||||||
|
|
||||||
virtual glm::vec2 getViewportDimensions() const;
|
virtual glm::vec2 getViewportDimensions() const;
|
||||||
virtual glm::vec4 getRecommendedOverlayRect() const;
|
virtual QVariant getRecommendedOverlayRect() const;
|
||||||
|
|
||||||
/// Factory to create an InputController
|
/// Factory to create an InputController
|
||||||
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
||||||
|
|
|
@ -140,6 +140,18 @@ QVariant vec3toVariant(const glm::vec3 &vec3) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant vec4toVariant(const glm::vec4& vec4) {
|
||||||
|
if (isNaN(vec4.x) || isNaN(vec4.y) || isNaN(vec4.z) || isNaN(vec4.w)) {
|
||||||
|
// if vec4 contains a NaN don't try to convert it
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
QVariantMap result;
|
||||||
|
result["x"] = vec4.x;
|
||||||
|
result["y"] = vec4.y;
|
||||||
|
result["z"] = vec4.z;
|
||||||
|
result["w"] = vec4.w;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector) {
|
QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector) {
|
||||||
QScriptValue array = engine->newArray();
|
QScriptValue array = engine->newArray();
|
||||||
|
@ -194,6 +206,46 @@ glm::vec3 vec3FromVariant(const QVariant &object) {
|
||||||
return vec3FromVariant(object, valid);
|
return vec3FromVariant(object, valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec4 vec4FromVariant(const QVariant &object, bool& valid) {
|
||||||
|
glm::vec4 v;
|
||||||
|
valid = false;
|
||||||
|
if (!object.isValid() || object.isNull()) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
else if (object.canConvert<float>()) {
|
||||||
|
v = glm::vec4(object.toFloat());
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
else if (object.canConvert<QVector4D>()) {
|
||||||
|
auto qvec4 = qvariant_cast<QVector4D>(object);
|
||||||
|
v.x = qvec4.x();
|
||||||
|
v.y = qvec4.y();
|
||||||
|
v.z = qvec4.z();
|
||||||
|
v.w = qvec4.w();
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto map = object.toMap();
|
||||||
|
auto x = map["x"];
|
||||||
|
auto y = map["y"];
|
||||||
|
auto z = map["z"];
|
||||||
|
auto w = map["w"];
|
||||||
|
if (x.canConvert<float>() && y.canConvert<float>() && z.canConvert<float>() && w.canConvert<float>()) {
|
||||||
|
v.x = x.toFloat();
|
||||||
|
v.y = y.toFloat();
|
||||||
|
v.z = z.toFloat();
|
||||||
|
v.w = w.toFloat();
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec4 vec4FromVariant(const QVariant &object) {
|
||||||
|
bool valid = false;
|
||||||
|
return vec4FromVariant(object, valid);
|
||||||
|
}
|
||||||
|
|
||||||
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
|
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) {
|
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) {
|
||||||
|
|
|
@ -43,6 +43,9 @@ void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4);
|
||||||
// Vec4
|
// Vec4
|
||||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4);
|
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4);
|
||||||
void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4);
|
void vec4FromScriptValue(const QScriptValue& object, glm::vec4& vec4);
|
||||||
|
QVariant vec4toVariant(const glm::vec4& vec4);
|
||||||
|
glm::vec4 vec4FromVariant(const QVariant &object, bool& valid);
|
||||||
|
glm::vec4 vec4FromVariant(const QVariant &object);
|
||||||
|
|
||||||
// Vec3
|
// Vec3
|
||||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||||
|
|
Loading…
Reference in a new issue