Merge pull request #7690 from ZappoMan/improveHMD

Introduce "recommended overlay rectangle" to display plugins
This commit is contained in:
Brad Hefta-Gaub 2016-04-18 18:04:21 -07:00
commit 0ac9601ea7
15 changed files with 224 additions and 42 deletions

View file

@ -14,11 +14,9 @@ Script.load("edit.js");
Script.load("examples.js"); Script.load("examples.js");
Script.load("selectAudioDevice.js"); Script.load("selectAudioDevice.js");
Script.load("notifications.js"); Script.load("notifications.js");
Script.load("users.js");
Script.load("controllers/handControllerGrab.js"); Script.load("controllers/handControllerGrab.js");
Script.load("controllers/squeezeHands.js"); Script.load("controllers/squeezeHands.js");
Script.load("grab.js"); Script.load("grab.js");
Script.load("directory.js"); Script.load("directory.js");
Script.load("dialTone.js"); Script.load("dialTone.js");
// Script.load("attachedEntitiesManager.js");
Script.load("depthReticle.js"); Script.load("depthReticle.js");

View file

@ -355,20 +355,36 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
}); });
} }
}; };
that.windowDimensions = Controller.getViewportDimensions();
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
var recommendedRect = Controller.getRecommendedOverlayRect();
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions();
that.origin = { x: recommendedRect.x, y: recommendedRect.y };
// Maybe fixme: Keeping the same percent of the window size isn't always the right thing. // Maybe fixme: Keeping the same percent of the window size isn't always the right thing.
// For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen". // For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen".
// If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below. // If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below.
that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients. that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients.
var fractionX = that.x / that.windowDimensions.x; var recommendedRect = Controller.getRecommendedOverlayRect();
var fractionY = that.y / that.windowDimensions.y; var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
that.windowDimensions = newSize || Controller.getViewportDimensions(); var originRelativeX = (that.x - that.origin.x);
that.move(fractionX * that.windowDimensions.x, fractionY * that.windowDimensions.y); var originRelativeY = (that.y - that.origin.y);
var fractionX = clamp(originRelativeX / that.windowDimensions.x, 0, 1);
var fractionY = clamp(originRelativeY / that.windowDimensions.y, 0, 1);
that.windowDimensions = newSize || recommendedDimmensions;
that.origin = { x: recommendedRect.x, y: recommendedRect.y };
var newX = (fractionX * that.windowDimensions.x) + recommendedRect.x;
var newY = (fractionY * that.windowDimensions.y) + recommendedRect.y;
that.move(newX, newY);
}; };
if (optionalPersistenceKey) { if (optionalPersistenceKey) {
this.fractionKey = optionalPersistenceKey + '.fraction'; this.fractionKey = optionalPersistenceKey + '.fraction';
this.save = function () { this.save = function () {
var screenSize = Controller.getViewportDimensions(); var recommendedRect = Controller.getRecommendedOverlayRect();
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
if (screenSize.x > 0 && screenSize.y > 0) { if (screenSize.x > 0 && screenSize.y > 0) {
// Guard against invalid screen size that can occur at shut-down. // Guard against invalid screen size that can occur at shut-down.
var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y}; var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y};
@ -411,7 +427,9 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y); that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y);
}; };
that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport. that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport.
var currentWindowSize = Controller.getViewportDimensions(); var recommendedRect = Controller.getRecommendedOverlayRect();
var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height };
if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) { if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) {
that.onResizeViewport(currentWindowSize); that.onResizeViewport(currentWindowSize);
} }
@ -434,7 +452,8 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
} }
if (this.fractionKey || optionalInitialPositionFunction) { if (this.fractionKey || optionalInitialPositionFunction) {
var savedFraction = JSON.parse(Settings.getValue(this.fractionKey) || '0'); // getValue can answer empty string var savedFraction = JSON.parse(Settings.getValue(this.fractionKey) || '0'); // getValue can answer empty string
var screenSize = Controller.getViewportDimensions(); var recommendedRect = Controller.getRecommendedOverlayRect();
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
if (savedFraction) { if (savedFraction) {
// If we have saved data, keep the toolbar at the same proportion of the screen width/height. // If we have saved data, keep the toolbar at the same proportion of the screen width/height.
that.move(savedFraction.x * screenSize.x, savedFraction.y * screenSize.y); that.move(savedFraction.x * screenSize.x, savedFraction.y * screenSize.y);

View file

@ -23,6 +23,8 @@ Hifi.AvatarInputs {
readonly property int mirrorWidth: 265 readonly property int mirrorWidth: 265
readonly property int iconSize: 24 readonly property int iconSize: 24
readonly property int iconPadding: 5 readonly property int iconPadding: 5
readonly property bool shouldReposition: true
Settings { Settings {
category: "Overlay.AvatarInputs" category: "Overlay.AvatarInputs"

View file

@ -21,8 +21,11 @@ FocusScope {
objectName: "desktop" objectName: "desktop"
anchors.fill: parent anchors.fill: parent
onHeightChanged: d.repositionAll(); property rect recommendedRect: rect(0,0,0,0);
onWidthChanged: d.repositionAll();
onHeightChanged: d.handleSizeChanged();
onWidthChanged: d.handleSizeChanged();
// 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.
@ -50,6 +53,20 @@ FocusScope {
QtObject { QtObject {
id: d id: d
function handleSizeChanged() {
var oldRecommendedRect = recommendedRect;
var newRecommendedRectJS = Controller.getRecommendedOverlayRect();
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
newRecommendedRectJS.width,
newRecommendedRectJS.height);
if (oldRecommendedRect != Qt.rect(0,0,0,0)
&& oldRecommendedRect != newRecommendedRect) {
d.repositionAll();
}
recommendedRect = newRecommendedRect;
}
function findChild(item, name) { function findChild(item, name) {
for (var i = 0; i < item.children.length; ++i) { for (var i = 0; i < item.children.length; ++i) {
if (item.children[i].objectName === name) { if (item.children[i].objectName === name) {
@ -202,12 +219,42 @@ FocusScope {
// } // }
} }
function getRepositionChildren(predicate) {
var currentWindows = [];
if (!desktop) {
console.log("Could not find desktop");
return currentWindows;
}
for (var i = 0; i < desktop.children.length; ++i) {
var child = desktop.children[i];
if (child.shouldReposition === true && (!predicate || predicate(child))) {
currentWindows.push(child)
}
}
return currentWindows;
}
function repositionAll() { function repositionAll() {
var oldRecommendedRect = recommendedRect;
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
var newRecommendedRect = Controller.getRecommendedOverlayRect();
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
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]); var targetWindow = windows[i];
if (targetWindow.visible) {
repositionWindow(targetWindow, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
}
} }
// also reposition the other children that aren't top level windows but want to be repositioned
var otherChildren = d.getRepositionChildren();
for (var i = 0; i < otherChildren.length; ++i) {
var child = otherChildren[i];
repositionWindow(child, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
}
} }
} }
@ -232,38 +279,56 @@ FocusScope {
targetWindow.focus = true; targetWindow.focus = true;
} }
reposition(targetWindow); var oldRecommendedRect = recommendedRect;
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
var newRecommendedRect = Controller.getRecommendedOverlayRect();
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
showDesktop(); showDesktop();
} }
function reposition(item) { function repositionWindow(targetWindow, forceReposition,
oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions) {
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 maxX = recommended.x + recommended.width;
var maxY = recommended.y + recommended.height;
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 > maxX || (targetWindow.x + targetWindow.width) < recommended.x) ||
(targetWindow.y > maxY || (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 var originRelativeX = (targetWindow.x - oldRecommendedRect.x);
// var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y); var originRelativeY = (targetWindow.y - oldRecommendedRect.y);
// var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height); if (isNaN(originRelativeX)) {
// newPosition = Utils.clampVector(newPosition, minPosition, maxPosition); originRelativeX = 0;
// newPosition = Utils.randomPosition(minPosition, maxPosition); }
newPosition = Qt.vector2d(desktop.width / 2 - targetWindow.width / 2, if (isNaN(originRelativeY)) {
desktop.height / 2 - targetWindow.height / 2); 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;

View file

@ -2681,8 +2681,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()) {
@ -4894,19 +4892,44 @@ QRect Application::getRenderingGeometry() const {
} }
glm::uvec2 Application::getUiSize() const { glm::uvec2 Application::getUiSize() const {
return getActiveDisplayPlugin()->getRecommendedUiSize(); static const uint MIN_SIZE = 1;
glm::uvec2 result(MIN_SIZE);
if (_displayPlugin) {
result = getActiveDisplayPlugin()->getRecommendedUiSize();
}
return result;
}
QRect Application::getRecommendedOverlayRect() const {
auto uiSize = getUiSize();
QRect result(0, 0, uiSize.x, uiSize.y);
if (_displayPlugin) {
result = getActiveDisplayPlugin()->getRecommendedOverlayRect();
}
return result;
} }
QSize Application::getDeviceSize() const { QSize Application::getDeviceSize() const {
return fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize()); static const int MIN_SIZE = 1;
QSize result(MIN_SIZE, MIN_SIZE);
if (_displayPlugin) {
result = fromGlm(getActiveDisplayPlugin()->getRecommendedRenderSize());
}
return result;
} }
bool Application::isThrottleRendering() const { bool Application::isThrottleRendering() const {
return getActiveDisplayPlugin()->isThrottled(); if (_displayPlugin) {
return getActiveDisplayPlugin()->isThrottled();
}
return false;
} }
bool Application::hasFocus() const { bool Application::hasFocus() const {
return getActiveDisplayPlugin()->hasFocus(); if (_displayPlugin) {
return getActiveDisplayPlugin()->hasFocus();
}
return (QApplication::activeWindow() != nullptr);
} }
glm::vec2 Application::getViewportDimensions() const { glm::vec2 Application::getViewportDimensions() const {

View file

@ -117,6 +117,7 @@ public:
QRect getRenderingGeometry() const; QRect getRenderingGeometry() const;
glm::uvec2 getUiSize() const; glm::uvec2 getUiSize() const;
QRect getRecommendedOverlayRect() const;
QSize getDeviceSize() const; QSize getDeviceSize() const;
bool hasFocus() const; bool hasFocus() const;

View file

@ -80,6 +80,11 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
return qApp->getUiSize(); return qApp->getUiSize();
} }
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
auto rect = qApp->getRecommendedOverlayRect();
return qRectToVariant(rect);
}
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
// This is where we retrieve the Device Tracker category and then the sub tracker within it // This is where we retrieve the Device Tracker category and then the sub tracker within it
auto icIt = _inputControllers.find(0); auto icIt = _inputControllers.find(0);

View file

@ -96,6 +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 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);

View file

@ -34,6 +34,7 @@ static const float reticleSize = TWO_PI / 100.0f;
static QString _tooltipId; static QString _tooltipId;
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(3960, 1188); // ~10% more pixel density than old version, 72dx240d FOV const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(3960, 1188); // ~10% more pixel density than old version, 72dx240d FOV
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(956, 0, 2048, 1188); // don't include entire width only center 2048
const float CompositorHelper::VIRTUAL_UI_ASPECT_RATIO = (float)VIRTUAL_SCREEN_SIZE.x / (float)VIRTUAL_SCREEN_SIZE.y; const float CompositorHelper::VIRTUAL_UI_ASPECT_RATIO = (float)VIRTUAL_SCREEN_SIZE.x / (float)VIRTUAL_SCREEN_SIZE.y;
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI * 3.0f / 2.0f, PI * 3.0f / 2.0f / VIRTUAL_UI_ASPECT_RATIO); const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI * 3.0f / 2.0f, PI * 3.0f / 2.0f / VIRTUAL_UI_ASPECT_RATIO);
const vec2 CompositorHelper::MOUSE_EXTENTS_ANGULAR_SIZE = vec2(PI * 2.0f, PI * 0.95f); // horizontal: full sphere, vertical: ~5deg from poles const vec2 CompositorHelper::MOUSE_EXTENTS_ANGULAR_SIZE = vec2(PI * 2.0f, PI * 0.95f); // horizontal: full sphere, vertical: ~5deg from poles

View file

@ -42,6 +42,7 @@ class CompositorHelper : public QObject, public Dependency {
Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop) Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop)
public: public:
static const uvec2 VIRTUAL_SCREEN_SIZE; static const uvec2 VIRTUAL_SCREEN_SIZE;
static const QRect VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
static const float VIRTUAL_UI_ASPECT_RATIO; static const float VIRTUAL_UI_ASPECT_RATIO;
static const vec2 VIRTUAL_UI_TARGET_FOV; static const vec2 VIRTUAL_UI_TARGET_FOV;
static const vec2 MOUSE_EXTENTS_ANGULAR_SIZE; static const vec2 MOUSE_EXTENTS_ANGULAR_SIZE;

View file

@ -34,6 +34,11 @@ glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const {
return CompositorHelper::VIRTUAL_SCREEN_SIZE; return CompositorHelper::VIRTUAL_SCREEN_SIZE;
} }
QRect HmdDisplayPlugin::getRecommendedOverlayRect() const {
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
}
bool HmdDisplayPlugin::internalActivate() { bool HmdDisplayPlugin::internalActivate() {
_monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW); _monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW);

View file

@ -26,6 +26,8 @@ public:
void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final; void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final;
bool isDisplayVisible() const override { return isHmdMounted(); } bool isDisplayVisible() const override { return isHmdMounted(); }
QRect getRecommendedOverlayRect() const override final;
virtual glm::mat4 getHeadPose() const override; virtual glm::mat4 getHeadPose() const override;

View file

@ -105,6 +105,12 @@ public:
return aspect(getRecommendedRenderSize()); return aspect(getRecommendedRenderSize());
} }
// The recommended bounds for primary overlay placement
virtual QRect getRecommendedOverlayRect() const {
auto recommendedSize = getRecommendedUiSize();
return QRect(0, 0, recommendedSize.x, recommendedSize.y);
}
// Stereo specific methods // Stereo specific methods
virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const { virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
return baseProjection; return baseProjection;

View file

@ -128,7 +128,7 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
vec3.z = object.property("z").toVariant().toFloat(); 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.x != vec3.x || vec3.y != vec3.y || vec3.z != vec3.z) {
// if vec3 contains a NaN don't try to convert it // if vec3 contains a NaN don't try to convert it
return QVariant(); return QVariant();
@ -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();
@ -150,7 +162,7 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::
} }
glm::vec3 vec3FromVariant(const QVariant &object, bool& valid) { glm::vec3 vec3FromVariant(const QVariant& object, bool& valid) {
glm::vec3 v; glm::vec3 v;
valid = false; valid = false;
if (!object.isValid() || object.isNull()) { if (!object.isValid() || object.isNull()) {
@ -189,12 +201,49 @@ glm::vec3 vec3FromVariant(const QVariant &object, bool& valid) {
return v; return v;
} }
glm::vec3 vec3FromVariant(const QVariant &object) { glm::vec3 vec3FromVariant(const QVariant& object) {
bool valid = false; bool valid = false;
return vec3FromVariant(object, valid); return vec3FromVariant(object, valid);
} }
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) { 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(); 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) {
// if quat contains a NaN don't try to convert it // if quat contains a NaN don't try to convert it
@ -207,7 +256,7 @@ QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
return obj; return obj;
} }
void quatFromScriptValue(const QScriptValue &object, glm::quat &quat) { void quatFromScriptValue(const QScriptValue& object, glm::quat &quat) {
quat.x = object.property("x").toVariant().toFloat(); quat.x = object.property("x").toVariant().toFloat();
quat.y = object.property("y").toVariant().toFloat(); quat.y = object.property("y").toVariant().toFloat();
quat.z = object.property("z").toVariant().toFloat(); quat.z = object.property("z").toVariant().toFloat();
@ -245,12 +294,12 @@ glm::quat quatFromVariant(const QVariant &object, bool& isValid) {
return q; return q;
} }
glm::quat quatFromVariant(const QVariant &object) { glm::quat quatFromVariant(const QVariant& object) {
bool valid = false; bool valid = false;
return quatFromVariant(object, valid); return quatFromVariant(object, valid);
} }
QVariant quatToVariant(const glm::quat &quat) { QVariant quatToVariant(const glm::quat& quat) {
if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z) { if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z) {
// if vec3 contains a NaN don't try to convert it // if vec3 contains a NaN don't try to convert it
return QVariant(); return QVariant();

View file

@ -43,12 +43,15 @@ 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);
void vec3FromScriptValue(const QScriptValue &object, 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, bool& valid);
glm::vec3 vec3FromVariant(const QVariant &object); glm::vec3 vec3FromVariant(const QVariant &object);
@ -71,9 +74,10 @@ glm::quat quatFromVariant(const QVariant &object);
// Rect // Rect
QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect); QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect);
void qRectFromScriptValue(const QScriptValue& object, QRect& rect); void qRectFromScriptValue(const QScriptValue& object, QRect& rect);
QVariant qRectToVariant(const QRect& rect);
QRect qRectFromVariant(const QVariant& object, bool& isValid); QRect qRectFromVariant(const QVariant& object, bool& isValid);
QRect qRectFromVariant(const QVariant& object);
QVariant qRectToVariant(const QRect& rect);
// xColor // xColor
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color); QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);