mirror of
https://github.com/overte-org/overte.git
synced 2025-04-29 11:42:33 +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 "styles"
|
||||
import "windows"
|
||||
import "windows-uit"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
|
|
@ -21,8 +21,29 @@ FocusScope {
|
|||
objectName: "desktop"
|
||||
anchors.fill: parent
|
||||
|
||||
onHeightChanged: d.repositionAll();
|
||||
onWidthChanged: d.repositionAll();
|
||||
property vector4d recommendedRect: vector4d(0,0,0,0);
|
||||
|
||||
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
|
||||
// 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() {
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
reposition(windows[i]);
|
||||
}
|
||||
|
||||
// also reposition the avatar inputs window if need be
|
||||
repositionWindow(getAvatarInputsWindow(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,32 +270,62 @@ FocusScope {
|
|||
}
|
||||
|
||||
function reposition(item) {
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
repositionWindow(targetWindow, true);
|
||||
}
|
||||
|
||||
function repositionWindow(targetWindow, forceReposition) {
|
||||
if (desktop.width === 0 || desktop.height === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
var recommended = Controller.getRecommendedOverlayRect();
|
||||
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) ||
|
||||
(targetWindow.y > desktop.height || (targetWindow.y + targetWindow.height) < 0)) {
|
||||
|
||||
// if we asked to force reposition, or if the window is completely outside of the recommended rectangle, reposition it
|
||||
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.y = -1
|
||||
}
|
||||
|
||||
|
||||
if (newPosition.x === -1 && newPosition.y === -1) {
|
||||
// Set initial window position
|
||||
// var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y);
|
||||
// var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height);
|
||||
// newPosition = Utils.clampVector(newPosition, 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.y = newPosition.y;
|
||||
|
|
|
@ -2669,8 +2669,6 @@ void Application::idle(uint64_t now) {
|
|||
_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.
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
|
||||
|
@ -4882,23 +4880,41 @@ QRect Application::getRenderingGeometry() const {
|
|||
}
|
||||
|
||||
glm::uvec2 Application::getUiSize() const {
|
||||
return getActiveDisplayPlugin()->getRecommendedUiSize();
|
||||
glm::uvec2 result;
|
||||
if (_displayPlugin) {
|
||||
result = getActiveDisplayPlugin()->getRecommendedUiSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::uvec4 Application::getRecommendedOverlayRect() const {
|
||||
return getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
||||
glm::uvec4 result;
|
||||
if (_displayPlugin) {
|
||||
result = getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QSize Application::getDeviceSize() const {
|
||||
return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
||||
QSize result;
|
||||
if (_displayPlugin) {
|
||||
result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Application::isThrottleRendering() const {
|
||||
return getActiveDisplayPlugin()->isThrottled();
|
||||
if (_displayPlugin) {
|
||||
return getActiveDisplayPlugin()->isThrottled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Application::hasFocus() const {
|
||||
return getActiveDisplayPlugin()->hasFocus();
|
||||
if (_displayPlugin) {
|
||||
return getActiveDisplayPlugin()->hasFocus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec2 Application::getViewportDimensions() const {
|
||||
|
|
|
@ -80,9 +80,9 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
|||
return qApp->getUiSize();
|
||||
}
|
||||
|
||||
glm::vec4 ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||
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) {
|
||||
|
|
|
@ -96,7 +96,7 @@ public slots:
|
|||
virtual void releaseJoystick(int joystickIndex);
|
||||
|
||||
virtual glm::vec2 getViewportDimensions() const;
|
||||
virtual glm::vec4 getRecommendedOverlayRect() const;
|
||||
virtual QVariant getRecommendedOverlayRect() const;
|
||||
|
||||
/// Factory to create an InputController
|
||||
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
||||
|
|
|
@ -128,7 +128,7 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
|
|||
vec3.z = object.property("z").toVariant().toFloat();
|
||||
}
|
||||
|
||||
QVariant vec3toVariant(const glm::vec3 &vec3) {
|
||||
QVariant vec3toVariant(const glm::vec3& vec3) {
|
||||
if (vec3.x != vec3.x || vec3.y != vec3.y || vec3.z != vec3.z) {
|
||||
// if vec3 contains a NaN don't try to convert it
|
||||
return QVariant();
|
||||
|
@ -140,6 +140,18 @@ QVariant vec3toVariant(const glm::vec3 &vec3) {
|
|||
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 array = engine->newArray();
|
||||
|
@ -194,6 +206,46 @@ glm::vec3 vec3FromVariant(const QVariant &object) {
|
|||
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 obj = engine->newObject();
|
||||
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) {
|
||||
|
|
|
@ -43,12 +43,15 @@ void mat4FromScriptValue(const QScriptValue& object, glm::mat4& mat4);
|
|||
// Vec4
|
||||
QScriptValue vec4toScriptValue(QScriptEngine* engine, const 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
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||
void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
|
||||
QVariant vec3toVariant(const glm::vec3 &vec3);
|
||||
QVariant vec3toVariant(const glm::vec3& vec3);
|
||||
glm::vec3 vec3FromVariant(const QVariant &object, bool& valid);
|
||||
glm::vec3 vec3FromVariant(const QVariant &object);
|
||||
|
||||
|
|
Loading…
Reference in a new issue