From: Chris Adams Date: Thu, 14 Jul 2011 05:40:30 +0000 (+1000) Subject: Add support for a vector4d type in QML X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=eaf52673ef38b4d7a14f9fb9f258d8f1c6097401;p=konrad%2Fqtdeclarative.git Add support for a vector4d type in QML QVector4D is a value-type which is supported but was not able to be constructed using a Qt object function. This commit allows properties of vector4d type to be constructed, and adds a function to the global Qt object and adds unit tests to ensure that it behaves correctly. Task-number: QTBUG-18559 Change-Id: I96509a4f496b644d20fdb1d977d0afe430d89e13 Reviewed-on: http://codereview.qt.nokia.com/1626 Reviewed-by: Qt Sanity Bot Reviewed-by: Aaron Kennedy --- diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index f39e1ab..7cc8422 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -312,6 +312,13 @@ bool QDeclarativeCompiler::testLiteralAssignment(const QMetaProperty &prop, if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); } break; + case QVariant::Vector4D: + { + bool ok; + QDeclarativeStringConverters::vector4DFromString(string, &ok); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected")); + } + break; default: { int t = prop.userType(); @@ -554,6 +561,18 @@ void QDeclarativeCompiler::genLiteralAssignment(const QMetaProperty &prop, instr.storeVector3D.vector.zp = vector.z(); } break; + case QVariant::Vector4D: + { + bool ok; + QVector4D vector = QDeclarativeStringConverters::vector4DFromString(string, &ok); + instr.setType(QDeclarativeInstruction::StoreVector4D); + instr.storeVector4D.propertyIndex = prop.propertyIndex(); + instr.storeVector4D.vector.xp = vector.x(); + instr.storeVector4D.vector.yp = vector.y(); + instr.storeVector4D.vector.zp = vector.z(); + instr.storeVector4D.vector.wp = vector.w(); + } + break; default: { int t = prop.userType(); diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index f99351b..f5bd6e9 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -132,6 +132,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreVector3D: qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.vector.xp << "\t" << instr->storeVector3D.vector.yp << "\t" << instr->storeVector3D.vector.zp; break; + case QDeclarativeInstruction::StoreVector4D: + qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR4D\t\t" << instr->storeVector4D.propertyIndex << "\t" << instr->storeVector4D.vector.xp << "\t" << instr->storeVector4D.vector.yp << "\t" << instr->storeVector4D.vector.zp << "\t" << instr->storeVector4D.vector.wp; + break; case QDeclarativeInstruction::StoreVariant: qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value); break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index a48c44c..f980027 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -88,6 +88,7 @@ QT_BEGIN_NAMESPACE F(StoreRect, storeRect) \ F(StoreRectF, storeRectF) \ F(StoreVector3D, storeVector3D) \ + F(StoreVector4D, storeVector4D) \ F(StoreObject, storeObject) \ F(AssignCustomType, assignCustomType) \ F(AssignSignalObject, assignSignalObject) \ @@ -405,6 +406,16 @@ union QDeclarativeInstruction float zp; } vector; }; + struct instr_storeVector4D { + QML_INSTR_HEADER + int propertyIndex; + struct QVector4D { + float xp; + float yp; + float zp; + float wp; + } vector; + }; instr_common common; instr_init init; @@ -440,6 +451,7 @@ union QDeclarativeInstruction instr_storeRect storeRect; instr_storeRectF storeRectF; instr_storeVector3D storeVector3D; + instr_storeVector4D storeVector4D; instr_storeObject storeObject; instr_assignCustomType assignCustomType; instr_storeSignal storeSignal; diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index d7cfe2e..b949adf 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -93,6 +94,8 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) if (ok) return QVariant(sz); QVector3D v = vector3DFromString(s, &ok); if (ok) return QVariant::fromValue(v); + QVector4D v4 = vector4DFromString(s, &ok); + if (ok) return QVariant::fromValue(v4); return QVariant(s); } @@ -128,6 +131,8 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int p return QVariant::fromValue(rectFFromString(s, ok).toRect()); case QMetaType::QVector3D: return QVariant::fromValue(vector3DFromString(s, ok)); + case QMetaType::QVector4D: + return QVariant::fromValue(vector4DFromString(s, ok)); default: if (ok) *ok = false; return QVariant(); @@ -275,4 +280,32 @@ QVector3D QDeclarativeStringConverters::vector3DFromString(const QString &s, boo return QVector3D(xCoord, yCoord, zCoord); } +//expects input of "x,y,z,w" +QVector4D QDeclarativeStringConverters::vector4DFromString(const QString &s, bool *ok) +{ + if (s.count(QLatin1Char(',')) != 3) { + if (ok) + *ok = false; + return QVector4D(); + } + + bool xGood, yGood, zGood, wGood; + int index = s.indexOf(QLatin1Char(',')); + int index2 = s.indexOf(QLatin1Char(','), index+1); + int index3 = s.indexOf(QLatin1Char(','), index2+1); + qreal xCoord = s.left(index).toDouble(&xGood); + qreal yCoord = s.mid(index+1, index2-index-1).toDouble(&yGood); + qreal zCoord = s.mid(index2+1, index3-index2-1).toDouble(&zGood); + qreal wCoord = s.mid(index3+1).toDouble(&wGood); + if (!xGood || !yGood || !zGood || !wGood) { + if (ok) + *ok = false; + return QVector4D(); + } + + if (ok) + *ok = true; + return QVector4D(xCoord, yCoord, zCoord, wCoord); +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativestringconverters_p.h b/src/declarative/qml/qdeclarativestringconverters_p.h index a8c6359..2f93cd7 100644 --- a/src/declarative/qml/qdeclarativestringconverters_p.h +++ b/src/declarative/qml/qdeclarativestringconverters_p.h @@ -67,6 +67,7 @@ class QRectF; class QString; class QByteArray; class QVector3D; +class QVector4D; // XXX - Bauhaus currently uses these methods which is why they're exported namespace QDeclarativeStringConverters @@ -84,6 +85,7 @@ namespace QDeclarativeStringConverters QSizeF Q_DECLARATIVE_PRIVATE_EXPORT sizeFFromString(const QString &, bool *ok = 0); QRectF Q_DECLARATIVE_PRIVATE_EXPORT rectFFromString(const QString &, bool *ok = 0); QVector3D Q_DECLARATIVE_PRIVATE_EXPORT vector3DFromString(const QString &, bool *ok = 0); + QVector4D Q_DECLARATIVE_PRIVATE_EXPORT vector4DFromString(const QString &, bool *ok = 0); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 45e4745..6708b60 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -586,6 +586,16 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEObjectStack &stack, instr.propertyIndex, a); QML_END_INSTR(StoreVector3D) + QML_BEGIN_INSTR(StoreVector4D) + QObject *target = stack.top(); + CLEAN_PROPERTY(target, instr.propertyIndex); + + QVector4D *v = (QVector4D *)&instr.vector; + void *a[] = { v, 0, &status, &flags }; + QMetaObject::metacall(target, QMetaObject::WriteProperty, + instr.propertyIndex, a); + QML_END_INSTR(StoreVector4D) + QML_BEGIN_INSTR(StoreObject) QObject *assignObj = stack.pop(); QObject *target = stack.top(); diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index b2f98ac..db58aab 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -477,6 +477,7 @@ QVariant QV8Engine::toBasicVariant(v8::Handle value) #include +#include struct StaticQtMetaObject : public QObject { @@ -511,6 +512,7 @@ void QV8Engine::initializeGlobal(v8::Handle global) qt->Set(v8::String::New("point"), V8FUNCTION(point, this)); qt->Set(v8::String::New("size"), V8FUNCTION(size, this)); qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this)); + qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this)); qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this)); qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this)); @@ -846,6 +848,23 @@ v8::Handle QV8Engine::vector3d(const v8::Arguments &args) } /*! +\qmlmethod Qt::vector4d(real x, real y, real z, real w) +Returns a Vector4D with the specified \c x, \c y, \c z and \c w. +*/ +v8::Handle QV8Engine::vector4d(const v8::Arguments &args) +{ + if (args.Length() != 4) + V8THROW_ERROR("Qt.vector4d(): Invalid arguments"); + + double x = args[0]->NumberValue(); + double y = args[1]->NumberValue(); + double z = args[2]->NumberValue(); + double w = args[3]->NumberValue(); + + return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w))); +} + +/*! \qmlmethod color Qt::lighter(color baseColor, real factor) Returns a color lighter than \c baseColor by the \c factor provided. diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h index b3cc023..f493c67 100644 --- a/src/declarative/qml/v8/qv8engine_p.h +++ b/src/declarative/qml/v8/qv8engine_p.h @@ -435,6 +435,7 @@ protected: static v8::Handle point(const v8::Arguments &args); static v8::Handle size(const v8::Arguments &args); static v8::Handle vector3d(const v8::Arguments &args); + static v8::Handle vector4d(const v8::Arguments &args); static v8::Handle lighter(const v8::Arguments &args); static v8::Handle darker(const v8::Arguments &args); static v8::Handle tint(const v8::Arguments &args); diff --git a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp index e6e87d1..f432cbf 100644 --- a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp +++ b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp @@ -63,6 +63,7 @@ private slots: void rect(); void rectf(); void vector3d(); + void vector4d(); void time(); }; @@ -682,6 +683,24 @@ void tst_qdeclarativeinstruction::vector3d() QCOMPARE(vector.z(), (qreal)(float)12.0); } +void tst_qdeclarativeinstruction::vector4d() +{ + QCOMPARE(sizeof(QDeclarativeInstruction::instr_storeVector4D::QVector4D), sizeof(QVector4D)); + QCOMPARE(Q_ALIGNOF(QDeclarativeInstruction::instr_storeVector4D::QVector4D), Q_ALIGNOF(QVector4D)); + + QDeclarativeInstruction i; + i.storeVector4D.vector.xp = 8.2; + i.storeVector4D.vector.yp = 99.3; + i.storeVector4D.vector.zp = 12.0; + i.storeVector4D.vector.wp = 121.1; + + const QVector4D &vector = (const QVector4D &)(i.storeVector4D.vector); + QCOMPARE(vector.x(), (qreal)(float)8.2); + QCOMPARE(vector.y(), (qreal)(float)99.3); + QCOMPARE(vector.z(), (qreal)(float)12.0); + QCOMPARE(vector.w(), (qreal)(float)121.1); +} + void tst_qdeclarativeinstruction::time() { QCOMPARE(sizeof(QDeclarativeInstruction::instr_storeTime::QTime), sizeof(QTime)); diff --git a/tests/auto/declarative/qdeclarativelanguage/data/assignBasicTypes.qml b/tests/auto/declarative/qdeclarativelanguage/data/assignBasicTypes.qml index 9fe0ded..2313499 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/assignBasicTypes.qml +++ b/tests/auto/declarative/qdeclarativelanguage/data/assignBasicTypes.qml @@ -21,6 +21,7 @@ MyTypeObject { boolProperty: true variantProperty: "Hello World!" vectorProperty: "10,1,2.2" + vector4Property: "10,1,2.2,2.3" urlProperty: "main.qml" objectProperty: MyTypeObject { intProperty: 8 } diff --git a/tests/auto/declarative/qdeclarativelanguage/data/assignLiteralToVariant.qml b/tests/auto/declarative/qdeclarativelanguage/data/assignLiteralToVariant.qml index de476ae..f6f9a13 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/assignLiteralToVariant.qml +++ b/tests/auto/declarative/qdeclarativelanguage/data/assignLiteralToVariant.qml @@ -12,5 +12,6 @@ QtObject { property variant test9: String("#FF008800") property variant test10: true property variant test11: false + property variant test12: "100,100,100,100" } diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index c11bc33..dad0e23 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ class MyTypeObject : public QObject Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty) Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty) + Q_PROPERTY(QVector4D vector4Property READ vector4Property WRITE setVector4Property) Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty) Q_PROPERTY(QDeclarativeScriptString scriptProperty READ scriptProperty WRITE setScriptProperty) @@ -442,6 +444,14 @@ public: vectorPropertyValue = v; } + QVector4D vector4PropertyValue; + QVector4D vector4Property() const { + return vector4PropertyValue; + } + void setVector4Property(const QVector4D &v) { + vector4PropertyValue = v; + } + QUrl urlPropertyValue; QUrl urlProperty() const { return urlPropertyValue; diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index dfaf3d1..5e9bc41 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -564,6 +564,7 @@ void tst_qdeclarativelanguage::assignBasicTypes() QCOMPARE(object->boolProperty(), true); QCOMPARE(object->variantProperty(), QVariant("Hello World!")); QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2)); + QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3)); QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml"))); QVERIFY(object->objectProperty() != 0); MyTypeObject *child = qobject_cast(object->objectProperty()); @@ -610,6 +611,7 @@ void tst_qdeclarativelanguage::assignLiteralToVariant() QCOMPARE(object->property("test9").userType(), (int)QVariant::String); QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool); QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool); + QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D); QVERIFY(object->property("test1") == QVariant(1)); QVERIFY(object->property("test2") == QVariant((double)1.7)); @@ -622,6 +624,7 @@ void tst_qdeclarativelanguage::assignLiteralToVariant() QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800")))); QVERIFY(object->property("test10") == QVariant(bool(true))); QVERIFY(object->property("test11") == QVariant(bool(false))); + QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100))); delete object; } diff --git a/tests/auto/declarative/qdeclarativeqt/data/vector4.qml b/tests/auto/declarative/qdeclarativeqt/data/vector4.qml new file mode 100644 index 0000000..554dd1e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeqt/data/vector4.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 + +QtObject { + property variant test1: Qt.vector4d(1, 0, 0.9, 0.6); + property variant test2: Qt.vector4d(102, -10, -982.1, 10); + property variant test3: Qt.vector4d(102, -10, -982.1); + property variant test4: Qt.vector4d(102, -10, -982.1, 10, 15); +} diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp index 4a9bb45..d9cd2b8 100644 --- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp +++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp @@ -72,6 +72,7 @@ private slots: void point(); void size(); void vector(); + void vector4d(); void lighter(); void darker(); void tint(); @@ -243,6 +244,26 @@ void tst_qdeclarativeqt::vector() delete object; } +void tst_qdeclarativeqt::vector4d() +{ + QDeclarativeComponent component(&engine, TEST_FILE("vector4.qml")); + + QString warning1 = component.url().toString() + ":6: Error: Qt.vector4d(): Invalid arguments"; + QString warning2 = component.url().toString() + ":7: Error: Qt.vector4d(): Invalid arguments"; + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(qvariant_cast(object->property("test1")), QVector4D(1, 0, 0.9, 0.6)); + QCOMPARE(qvariant_cast(object->property("test2")), QVector4D(102, -10, -982.1, 10)); + QCOMPARE(qvariant_cast(object->property("test3")), QVector4D()); + QCOMPARE(qvariant_cast(object->property("test4")), QVector4D()); + + delete object; +} + void tst_qdeclarativeqt::lighter() { QDeclarativeComponent component(&engine, TEST_FILE("lighter.qml"));