From a50c3c1696873d1c7fd2d9c921816f5d04192e3e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 7 Nov 2014 12:04:03 -0800 Subject: [PATCH 01/18] Fix order of wrist and hand joints in Leapmotion controller --- examples/leapHands.js | 4 ++-- interface/src/devices/Leapmotion.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/leapHands.js b/examples/leapHands.js index 437637dc3f..47e4a51552 100644 --- a/examples/leapHands.js +++ b/examples/leapHands.js @@ -353,7 +353,7 @@ var leapHands = (function () { handOffset.x = -handOffset.x; // Hand rotation in camera coordinates ... - handRotation = wrists[h].controller.getAbsRotation(); + handRotation = hands[h].controller.getAbsRotation(); handRotation = { x: handRotation.z, y: handRotation.y, @@ -386,7 +386,7 @@ var leapHands = (function () { z: hands[h].zeroPosition.z - handOffset.z }; - handRotation = wrists[h].controller.getAbsRotation(); + handRotation = hands[h].controller.getAbsRotation(); handRotation = { x: handRotation.z, y: handRotation.y, diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp index a3794123ce..0c1433f216 100644 --- a/interface/src/devices/Leapmotion.cpp +++ b/interface/src/devices/Leapmotion.cpp @@ -70,8 +70,8 @@ Leapmotion::Leapmotion() : std::vector< Semantic > rootBones; rootBones.push_back("elbow"); - rootBones.push_back("hand"); rootBones.push_back("wrist"); + rootBones.push_back("hand"); std::vector< Semantic > fingers; fingers.push_back("thumb"); From 5f259791a30b92b0b3fe0f0ed145aac740a5b512 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 7 Nov 2014 12:07:04 -0800 Subject: [PATCH 02/18] Control "hand" joint with wrist position estimate if no "wrist" joint --- examples/leapHands.js | 127 +++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 46 deletions(-) diff --git a/examples/leapHands.js b/examples/leapHands.js index 47e4a51552..04253c8ab6 100644 --- a/examples/leapHands.js +++ b/examples/leapHands.js @@ -17,12 +17,16 @@ var leapHands = (function () { LEAP_ON_HMD_MENU_ITEM = "Leap Motion on HMD", LEAP_OFFSET = 0.019, // Thickness of Leap Motion plus HMD clip HMD_OFFSET = 0.070, // Eyeballs to front surface of Oculus DK2 TODO: Confirm and make depend on device and eye relief + hasHandAndWristJoints, + handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position + HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle hands, wrists, NUM_HANDS = 2, // 0 = left; 1 = right fingers, NUM_FINGERS = 5, // 0 = thumb; ...; 4 = pinky THUMB = 0, + MIDDLE_FINGER = 2, NUM_FINGER_JOINTS = 3, // 0 = metacarpal(hand)-proximal(finger) joint; ...; 2 = intermediate-distal joint MAX_HAND_INACTIVE_COUNT = 20, calibrationStatus, @@ -123,30 +127,41 @@ var leapHands = (function () { function finishCalibration() { var avatarPosition, - avatarOrientation, - avatarHandPosition, + handPosition, + middleFingerPosition, leapHandHeight, h; - if (hands[0].controller.isActive() && hands[1].controller.isActive()) { - leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0; - } else { - calibrationStatus = UNCALIBRATED; - return; + if (!isOnHMD) { + if (hands[0].controller.isActive() && hands[1].controller.isActive()) { + leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0; + } else { + calibrationStatus = UNCALIBRATED; + return; + } } avatarPosition = MyAvatar.position; - avatarOrientation = MyAvatar.orientation; for (h = 0; h < NUM_HANDS; h += 1) { - avatarHandPosition = MyAvatar.getJointPosition(hands[h].jointName); - hands[h].zeroPosition = { - x: avatarHandPosition.x - avatarPosition.x, - y: avatarHandPosition.y - avatarPosition.y, - z: avatarPosition.z - avatarHandPosition.z - }; - hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition); - hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight; + handPosition = MyAvatar.getJointPosition(hands[h].jointName); + if (!hasHandAndWristJoints) { + middleFingerPosition = MyAvatar.getJointPosition(fingers[h][MIDDLE_FINGER][0].jointName); + handToWristOffset[h] = Vec3.multiply(Vec3.subtract(handPosition, middleFingerPosition), 1.0 - HAND_OFFSET); + } + + if (isOnHMD) { + // Offset of Leap Motion origin from physical eye position + hands[h].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; + } else { + hands[h].zeroPosition = { + x: handPosition.x - avatarPosition.x, + y: handPosition.y - avatarPosition.y, + z: avatarPosition.z - handPosition.z + }; + hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition); + hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight; + } } MyAvatar.clearJointData("LeftHand"); @@ -161,6 +176,8 @@ var leapHands = (function () { } function calibrate() { + var jointNames, + i; calibrationStatus = CALIBRATING; @@ -168,6 +185,13 @@ var leapHands = (function () { avatarFaceModelURL = MyAvatar.faceModelURL; avatarSkeletonModelURL = MyAvatar.skeletonModelURL; + // Does this skeleton have both wrist and hand joints? + hasHandAndWristJoints = false; + jointNames = MyAvatar.getJointNames(); + for (i = 0; i < jointNames.length; i += 1) { + hasHandAndWristJoints = hasHandAndWristJoints || jointNames[i].toLowerCase() === "leftwrist"; + } + // Set avatar arms vertical, forearms horizontal, as "zero" position for calibration MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, -90.0)); MyAvatar.setJointData("LeftForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0)); @@ -176,6 +200,7 @@ var leapHands = (function () { MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0)); MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0)); + // Wait for arms to assume their positions before calculating Script.setTimeout(finishCalibration, CALIBRATION_TIME); } @@ -195,37 +220,34 @@ var leapHands = (function () { function setIsOnHMD() { isOnHMD = Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM); - if (isOnHMD) { - print("Leap Motion: Is on HMD"); - - // Offset of Leap Motion origin from physical eye position - hands[0].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; - hands[1].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; - - calibrationStatus = CALIBRATED; - } else { - print("Leap Motion: Is on desk"); - calibrationStatus = UNCALIBRATED; - } + print("Leap Motion: " + (isOnHMD ? "Is on HMD" : "Is on desk")); } function checkSettings() { - // There is no "scale changed" event so we need check periodically. - if (!isOnHMD && calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale + if (calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale || MyAvatar.faceModelURL !== avatarFaceModelURL - || MyAvatar.skeletonModelURL !== avatarSkeletonModelURL)) { - print("Leap Motion: Recalibrate because avatar body or scale changed"); + || MyAvatar.skeletonModelURL !== avatarSkeletonModelURL + || Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM) !== isOnHMD)) { + print("Leap Motion: Recalibrate..."); calibrationStatus = UNCALIBRATED; - } - // There is a "menu changed" event but we may as well check here. - if (isOnHMD !== Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM)) { setIsOnHMD(); } } function setUp() { + wrists = [ + { + jointName: "LeftWrist", + controller: Controller.createInputController("Spatial", "joint_L_wrist") + }, + { + jointName: "RightWrist", + controller: Controller.createInputController("Spatial", "joint_R_wrist") + } + ]; + hands = [ { jointName: "LeftHand", @@ -239,11 +261,6 @@ var leapHands = (function () { } ]; - wrists = [ - { controller: Controller.createInputController("Spatial", "joint_L_wrist") }, - { controller: Controller.createInputController("Spatial", "joint_R_wrist") } - ]; - // The Leap controller's first joint is the hand-metacarpal joint but this joint's data is not used because it's too // dependent on the model skeleton exactly matching the Leap skeleton; using just the second and subsequent joints // seems to work better over all. @@ -306,6 +323,8 @@ var leapHands = (function () { setIsOnHMD(); settingsTimer = Script.setInterval(checkSettings, 2000); + + calibrationStatus = UNCALIBRATED; } function moveHands() { @@ -314,6 +333,7 @@ var leapHands = (function () { j, side, handOffset, + wristOffset, handRotation, locRotation, cameraOrientation, @@ -330,10 +350,18 @@ var leapHands = (function () { } // Hand position ... + handOffset = hands[h].controller.getAbsTranslation(); + handRotation = hands[h].controller.getAbsRotation(); + if (isOnHMD) { + // Adjust to control wrist position if "hand" joint is at wrist ... + if (!hasHandAndWristJoints) { + wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]); + handOffset = Vec3.sum(handOffset, wristOffset); + } + // Hand offset in camera coordinates ... - handOffset = hands[h].controller.getAbsTranslation(); handOffset = { x: hands[h].zeroPosition.x - handOffset.x, y: hands[h].zeroPosition.y - handOffset.z, @@ -353,7 +381,6 @@ var leapHands = (function () { handOffset.x = -handOffset.x; // Hand rotation in camera coordinates ... - handRotation = hands[h].controller.getAbsRotation(); handRotation = { x: handRotation.z, y: handRotation.y, @@ -361,6 +388,7 @@ var leapHands = (function () { w: handRotation.w }; + // Hand rotation in avatar coordinates ... if (h === 0) { handRotation.x = -handRotation.x; handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation); @@ -371,7 +399,6 @@ var leapHands = (function () { handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 0, z: 1 }), handRotation); } - // Hand rotation in avatar coordinates ... cameraOrientation.x = -cameraOrientation.x; cameraOrientation.z = -cameraOrientation.z; handRotation = Quat.multiply(cameraOrientation, handRotation); @@ -379,14 +406,20 @@ var leapHands = (function () { } else { - handOffset = hands[h].controller.getAbsTranslation(); + // Adjust to control wrist position if "hand" joint is at wrist ... + if (!hasHandAndWristJoints) { + wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]); + handOffset = Vec3.sum(handOffset, wristOffset); + } + + // Hand offset in camera coordinates ... handOffset = { x: -handOffset.x, y: hands[h].zeroPosition.y + handOffset.y, z: hands[h].zeroPosition.z - handOffset.z }; - handRotation = hands[h].controller.getAbsRotation(); + // Hand rotation in camera coordinates ... handRotation = { x: handRotation.z, y: handRotation.y, @@ -394,6 +427,7 @@ var leapHands = (function () { w: handRotation.w }; + // Hand rotation in avatar coordinates ... if (h === 0) { handRotation.x = -handRotation.x; handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }), @@ -405,9 +439,10 @@ var leapHands = (function () { } } + // Set hand position and orientation ... MyAvatar.setJointModelPositionAndOrientation(hands[h].jointName, handOffset, handRotation, true); - // Finger joints ... + // Set finger joints ... for (i = 0; i < NUM_FINGERS; i += 1) { for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { if (fingers[h][i][j].controller !== null) { From 4fa5447c85a10a9a67623c7a66bf3f12cd63cbb8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 12 Nov 2014 12:13:57 -0800 Subject: [PATCH 03/18] Add overlay getProperty() for text overlay "text" property --- examples/overlaysExample.js | 3 +++ interface/src/ui/overlays/Overlay.cpp | 4 ++++ interface/src/ui/overlays/Overlay.h | 1 + interface/src/ui/overlays/Overlay2D.cpp | 4 ++++ interface/src/ui/overlays/Overlay2D.h | 1 + interface/src/ui/overlays/Overlays.cpp | 14 ++++++++++++++ interface/src/ui/overlays/Overlays.h | 3 +++ interface/src/ui/overlays/TextOverlay.cpp | 9 +++++++++ interface/src/ui/overlays/TextOverlay.h | 1 + 9 files changed, 40 insertions(+) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index fef502c761..e087bd3e3a 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -166,6 +166,9 @@ var clipboardPreview = Overlays.addOverlay("clipboard", { visible: true }); +// Demonstrate retrieving overlay properties +print("Text overlay text property value =\n" + Overlays.getProperty(text, "text")); +print("Text overlay unknown property vale =\n" + Overlays.getProperty(text, "unknown")); // value = undefined // When our script shuts down, we should clean up all of our overlays function scriptEnding() { diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 215119374e..762cf28dfd 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -104,6 +104,10 @@ void Overlay::setProperties(const QScriptValue& properties) { } } +QScriptValue Overlay::getProperty(const QString& property) { + return QScriptValue(); +} + xColor Overlay::getColor() { if (_colorPulse == 0.0f) { return _color; diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 81ddaf1a91..4752b33a4e 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -77,6 +77,7 @@ public: void setAlphaPulse(float value) { _alphaPulse = value; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); protected: float updatePulse(); diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index 0bdb8790cc..5a42a4fc2b 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -64,3 +64,7 @@ void Overlay2D::setProperties(const QScriptValue& properties) { //qDebug() << "set bounds to " << getBounds(); } } + +QScriptValue Overlay2D::getProperty(const QString& property) { + return Overlay::getProperty(property); +} diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 283e7b7b23..d0d75c9397 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -47,6 +47,7 @@ public: void setBounds(const QRect& bounds) { _bounds = bounds; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); protected: QRect _bounds; // where on the screen to draw diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 0192f9c216..5315a37f5d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -241,6 +241,20 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { return 0; // not found } +QScriptValue Overlays::getProperty(unsigned int id, const QString& property) { + Overlay* thisOverlay = NULL; + QReadLocker lock(&_lock); + if (_overlays2D.contains(id)) { + thisOverlay = _overlays2D[id]; + } else if (_overlays3D.contains(id)) { + thisOverlay = _overlays3D[id]; + } + if (thisOverlay) { + return thisOverlay->getProperty(property); + } + return QScriptValue(); +} + RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { float bestDistance = std::numeric_limits::max(); RayToOverlayIntersectionResult result; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 686b998267..9c1efe3a64 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -59,6 +59,9 @@ public slots: /// returns the top most 2D overlay at the screen point, or 0 if not overlay at that point unsigned int getOverlayAtPoint(const glm::vec2& point); + /// returns the value of specified property, or null if there is no such property + QScriptValue getProperty(unsigned int id, const QString& property); + /// returns details about the closest 3D Overlay hit by the pick ray RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray); diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 530b30a856..3bbdd70388 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -126,3 +126,12 @@ void TextOverlay::setProperties(const QScriptValue& properties) { } +QScriptValue TextOverlay::getProperty(const QString& property) { + if (property == "text") { + return _text; + } + + return Overlay::getProperty(property); +} + + diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index f7ff83e542..d43c701582 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -52,6 +52,7 @@ public: void setFontSize(int fontSize) { _fontSize = fontSize; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); private: From 8c3bedae9d1443b6c4737351642af5a958bf27f4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 12 Nov 2014 14:33:52 -0800 Subject: [PATCH 04/18] Add position vector and color object script value examples OverlayPropertyResult type is needed to successfully move QScriptValue objects from QScriptEngine in Overlays to QScriptEngine in script. --- examples/overlaysExample.js | 13 +++++++ interface/src/Application.cpp | 4 +- interface/src/ui/overlays/Base3DOverlay.cpp | 7 ++++ interface/src/ui/overlays/Base3DOverlay.h | 1 + interface/src/ui/overlays/Overlay.cpp | 6 ++- interface/src/ui/overlays/Overlay.h | 5 ++- interface/src/ui/overlays/Overlays.cpp | 41 +++++++++++++++++++-- interface/src/ui/overlays/Overlays.h | 15 +++++++- 8 files changed, 84 insertions(+), 8 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index e087bd3e3a..1dcb088d78 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -169,6 +169,19 @@ var clipboardPreview = Overlays.addOverlay("clipboard", { // Demonstrate retrieving overlay properties print("Text overlay text property value =\n" + Overlays.getProperty(text, "text")); print("Text overlay unknown property vale =\n" + Overlays.getProperty(text, "unknown")); // value = undefined +var cubePosition = Overlays.getProperty(cube, "position"); +print("Cube overlay position =\n" + + "x: " + cubePosition.x + "\n" + + "y: " + cubePosition.y + "\n" + + "z: " + cubePosition.z + ); +var cubeColor = Overlays.getProperty(cube, "color"); +print("Cube overlay color =\n" + + "red: " + cubeColor.red + "\n" + + "green: " + cubeColor.green + "\n" + + "blue: " + cubeColor.blue + ); +print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined // When our script shuts down, we should clean up all of our overlays function scriptEnding() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bb19ce3ca5..cf64bd55d6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3888,7 +3888,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool))); scriptEngine->registerGlobalObject("Overlays", &_overlays); - qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); + qScriptRegisterMetaType(scriptEngine, OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); + qScriptRegisterMetaType(scriptEngine, RayToOverlayIntersectionResultToScriptValue, + RayToOverlayIntersectionResultFromScriptValue); QScriptValue windowValue = scriptEngine->registerGlobalObject("Window", WindowScriptingInterface::getInstance()); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 89dd4d4b01..8c26bc1493 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -118,6 +118,13 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { } } +QScriptValue Base3DOverlay::getProperty(const QString& property) { + if (property == "position") { + return vec3toScriptValue(_scriptEngine, _position); + } + return Overlay::getProperty(property); +} + bool Base3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { return false; diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 75ce6b303d..7b7fa1a8f4 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -45,6 +45,7 @@ public: void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 762cf28dfd..ba7269c5dc 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -39,8 +39,9 @@ Overlay::Overlay() : { } -void Overlay::init(QGLWidget* parent) { +void Overlay::init(QGLWidget* parent, QScriptEngine* scriptEngine) { _parent = parent; + _scriptEngine = scriptEngine; } @@ -105,6 +106,9 @@ void Overlay::setProperties(const QScriptValue& properties) { } QScriptValue Overlay::getProperty(const QString& property) { + if (property == "color") { + return xColorToScriptValue(_scriptEngine, _color); + } return QScriptValue(); } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 4752b33a4e..192bb5fd40 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -19,6 +19,7 @@ #include #include +#include #include // for xColor #include @@ -36,7 +37,7 @@ public: Overlay(); ~Overlay(); - void init(QGLWidget* parent); + void init(QGLWidget* parent, QScriptEngine* scriptEngine); virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; @@ -101,6 +102,8 @@ protected: xColor _color; bool _visible; // should the overlay be drawn at all Anchor _anchor; + + QScriptEngine* _scriptEngine; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5315a37f5d..6fdd4e75d2 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "BillboardOverlay.h" #include "Circle3DOverlay.h" @@ -55,6 +56,7 @@ Overlays::~Overlays() { void Overlays::init(QGLWidget* parent) { _parent = parent; + _scriptEngine = new QScriptEngine(); } void Overlays::update(float deltatime) { @@ -179,7 +181,7 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope } unsigned int Overlays::addOverlay(Overlay* overlay) { - overlay->init(_parent); + overlay->init(_parent, _scriptEngine); QWriteLocker lock(&_lock); unsigned int thisID = _nextOverlayID; @@ -241,7 +243,8 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { return 0; // not found } -QScriptValue Overlays::getProperty(unsigned int id, const QString& property) { +OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& property) { + OverlayPropertyResult result; Overlay* thisOverlay = NULL; QReadLocker lock(&_lock); if (_overlays2D.contains(id)) { @@ -250,9 +253,39 @@ QScriptValue Overlays::getProperty(unsigned int id, const QString& property) { thisOverlay = _overlays3D[id]; } if (thisOverlay) { - return thisOverlay->getProperty(property); + result.value = thisOverlay->getProperty(property); } - return QScriptValue(); + return result; +} + +OverlayPropertyResult::OverlayPropertyResult() : + value(QScriptValue()) +{ +} + +QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& result) +{ + if (!result.value.isValid()) { + return QScriptValue::UndefinedValue; + } + + QScriptValue object = engine->newObject(); + if (result.value.isObject()) { + QScriptValueIterator it(result.value); + while (it.hasNext()) { + it.next(); + object.setProperty(it.name(), QScriptValue(it.value().toString())); + } + + } else { + object = result.value; + } + return object; +} + +void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayPropertyResult& result) +{ + result.value = value; } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 9c1efe3a64..ae48428bca 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -16,6 +16,17 @@ #include "Overlay.h" +class OverlayPropertyResult { +public: + OverlayPropertyResult(); + QScriptValue value; +}; + +Q_DECLARE_METATYPE(OverlayPropertyResult); + +QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value); +void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value); + class RayToOverlayIntersectionResult { public: RayToOverlayIntersectionResult(); @@ -27,6 +38,7 @@ public: QString extraInfo; }; + Q_DECLARE_METATYPE(RayToOverlayIntersectionResult); QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value); @@ -60,7 +72,7 @@ public slots: unsigned int getOverlayAtPoint(const glm::vec2& point); /// returns the value of specified property, or null if there is no such property - QScriptValue getProperty(unsigned int id, const QString& property); + OverlayPropertyResult getProperty(unsigned int id, const QString& property); /// returns details about the closest 3D Overlay hit by the pick ray RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray); @@ -76,6 +88,7 @@ private: QGLWidget* _parent; QReadWriteLock _lock; QReadWriteLock _deleteLock; + QScriptEngine* _scriptEngine; }; From 725d56d41f23dbe8a7af73e3dc79e778e90971a2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 12 Nov 2014 16:50:13 -0800 Subject: [PATCH 05/18] Add property getting for all 2D overlays --- examples/overlaysExample.js | 14 +++++++++- interface/src/ui/overlays/ImageOverlay.cpp | 14 ++++++++++ interface/src/ui/overlays/ImageOverlay.h | 1 + interface/src/ui/overlays/Overlay.cpp | 31 ++++++++++++++++++++++ interface/src/ui/overlays/Overlay2D.cpp | 21 +++++++++++++++ interface/src/ui/overlays/TextOverlay.cpp | 17 ++++++++++-- 6 files changed, 95 insertions(+), 3 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 1dcb088d78..d64a29046a 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -168,7 +168,19 @@ var clipboardPreview = Overlays.addOverlay("clipboard", { // Demonstrate retrieving overlay properties print("Text overlay text property value =\n" + Overlays.getProperty(text, "text")); -print("Text overlay unknown property vale =\n" + Overlays.getProperty(text, "unknown")); // value = undefined +print("Text overlay alpha =\n" + Overlays.getProperty(text, "alpha")); +print("Text overlay visible =\n" + Overlays.getProperty(text, "visible")); +print("Text overlay font size =\n" + Overlays.getProperty(text, "font").size); +print("Text overlay anchor =\n" + Overlays.getProperty(text, "anchor")); +print("Text overlay unknown property value =\n" + Overlays.getProperty(text, "unknown")); // value = undefined +var sliderBounds = Overlays.getProperty(slider, "bounds"); +print("Slider overlay bounds =\n" + + "x: " + sliderBounds.x + "\n" + + "y: " + sliderBounds.y + "\n" + + "width: " + sliderBounds.width + "\n" + + "height: " + sliderBounds.height + ); + var cubePosition = Overlays.getProperty(cube, "position"); print("Cube overlay position =\n" + "x: " + cubePosition.x + "\n" diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 3b9d95af2e..f2e93c2e0e 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -151,4 +151,18 @@ void ImageOverlay::setProperties(const QScriptValue& properties) { } } +QScriptValue ImageOverlay::getProperty(const QString& property) { + if (property == "subImage") { + QScriptValue subImage = _scriptEngine->newObject(); + subImage.setProperty("x", _fromImage.x()); + subImage.setProperty("y", _fromImage.y()); + subImage.setProperty("width", _fromImage.width()); + subImage.setProperty("height", _fromImage.height()); + return subImage; + } + if (property == "imageURL") { + return _imageURL.toString(); + } + return Overlay2D::getProperty(property); +} diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index ef1ead8c02..bf4f2860ad 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -44,6 +44,7 @@ public: void setClipFromSource(const QRect& bounds) { _fromImage = bounds; _wantClipFromImage = true; } void setImageURL(const QUrl& url); virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); private slots: void replyFinished(); // we actually want to hide this... diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index ba7269c5dc..a7c38946b7 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -109,6 +109,37 @@ QScriptValue Overlay::getProperty(const QString& property) { if (property == "color") { return xColorToScriptValue(_scriptEngine, _color); } + if (property == "alpha") { + return _alpha; + } + if (property == "glowLevel") { + return _glowLevel; + } + if (property == "pulseMax") { + return _pulseMax; + } + if (property == "pulseMin") { + return _pulseMin; + } + if (property == "pulsePeriod") { + return _pulsePeriod; + } + if (property == "glowLevelPulse") { + return _glowLevelPulse; + } + if (property == "alphaPulse") { + return _alphaPulse; + } + if (property == "colorPulse") { + return _colorPulse; + } + if (property == "visible") { + return _visible; + } + if (property == "anchor") { + return _anchor == MY_AVATAR ? "MyAvatar" : ""; + } + return QScriptValue(); } diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index 5a42a4fc2b..d71f8cac05 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -66,5 +66,26 @@ void Overlay2D::setProperties(const QScriptValue& properties) { } QScriptValue Overlay2D::getProperty(const QString& property) { + if (property == "bounds") { + QScriptValue bounds = _scriptEngine->newObject(); + bounds.setProperty("x", _bounds.x()); + bounds.setProperty("y", _bounds.y()); + bounds.setProperty("width", _bounds.width()); + bounds.setProperty("height", _bounds.height()); + return bounds; + } + if (property == "x") { + return _bounds.x(); + } + if (property == "y") { + return _bounds.y(); + } + if (property == "width") { + return _bounds.width(); + } + if (property == "height") { + return _bounds.height(); + } + return Overlay::getProperty(property); } diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 3bbdd70388..a17d381a85 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -125,13 +125,26 @@ void TextOverlay::setProperties(const QScriptValue& properties) { } } - QScriptValue TextOverlay::getProperty(const QString& property) { + if (property == "font") { + QScriptValue font = _scriptEngine->newObject(); + font.setProperty("size", _fontSize); + return font; + } if (property == "text") { return _text; } + if (property == "backgroundColor") { + return xColorToScriptValue(_scriptEngine, _backgroundColor); + } + if (property == "leftMargin") { + return _leftMargin; + } + if (property == "topMargin") { + return _topMargin; + } - return Overlay::getProperty(property); + return Overlay2D::getProperty(property); } From 9e19641a1d8987fef54eb907a3710e0e1365d561 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 12 Nov 2014 21:05:44 -0800 Subject: [PATCH 06/18] Add property getting for all 3D overlays --- examples/overlaysExample.js | 14 +++++++ interface/src/ui/overlays/Base3DOverlay.cpp | 21 +++++++++- .../src/ui/overlays/BillboardOverlay.cpp | 22 +++++++++++ interface/src/ui/overlays/BillboardOverlay.h | 1 + interface/src/ui/overlays/Circle3DOverlay.cpp | 39 +++++++++++++++++++ interface/src/ui/overlays/Circle3DOverlay.h | 1 + interface/src/ui/overlays/Grid3DOverlay.cpp | 11 ++++++ interface/src/ui/overlays/Grid3DOverlay.h | 1 + interface/src/ui/overlays/Line3DOverlay.cpp | 8 ++++ interface/src/ui/overlays/Line3DOverlay.h | 1 + .../src/ui/overlays/LocalVoxelsOverlay.cpp | 11 ++++++ .../src/ui/overlays/LocalVoxelsOverlay.h | 3 +- interface/src/ui/overlays/ModelOverlay.cpp | 31 +++++++++++++++ interface/src/ui/overlays/ModelOverlay.h | 2 + interface/src/ui/overlays/Planar3DOverlay.cpp | 8 ++++ interface/src/ui/overlays/Planar3DOverlay.h | 1 + interface/src/ui/overlays/Text3DOverlay.cpp | 27 +++++++++++++ interface/src/ui/overlays/Text3DOverlay.h | 1 + interface/src/ui/overlays/Volume3DOverlay.cpp | 8 ++++ interface/src/ui/overlays/Volume3DOverlay.h | 1 + 20 files changed, 210 insertions(+), 2 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index d64a29046a..5c7793185b 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -193,6 +193,20 @@ print("Cube overlay color =\n" + "green: " + cubeColor.green + "\n" + "blue: " + cubeColor.blue ); +var modelOverlayProperties = { + textures: { + filename1: "http://url1", + filename2: "http://url2" + } +} +var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); +var textures = Overlays.getProperty(modelOverlay, "textures"); +var textureValues = ""; +for (key in textures) { + textureValues += "\n" + key + ": " + textures[key]; +} +print("Model overlay textures =" + textureValues); +Overlays.deleteOverlay(modelOverlay); print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined // When our script shuts down, we should clean up all of our overlays diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 8c26bc1493..a83772d01b 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -119,9 +119,28 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { } QScriptValue Base3DOverlay::getProperty(const QString& property) { - if (property == "position") { + if (property == "position" || property == "start" || property == "p1" || property == "point") { return vec3toScriptValue(_scriptEngine, _position); } + if (property == "lineWidth") { + return _lineWidth; + } + if (property == "rotation") { + return quatToScriptValue(_scriptEngine, _rotation); + } + if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") { + return _isSolid; + } + if (property == "isWire" || property == "wire") { + return !_isSolid; + } + if (property == "isDashedLine" || property == "dashed") { + return _isDashedLine; + } + if (property == "ignoreRayIntersection") { + return _ignoreRayIntersection; + } + return Overlay::getProperty(property); } diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index c8d4877bb5..87b6dcc1c8 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -157,6 +157,28 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) { } } +QScriptValue BillboardOverlay::getProperty(const QString& property) { + if (property == "url") { + return _url; + } + if (property == "subImage") { + QScriptValue subImage = _scriptEngine->newObject(); + subImage.setProperty("x", _fromImage.x()); + subImage.setProperty("y", _fromImage.y()); + subImage.setProperty("width", _fromImage.width()); + subImage.setProperty("height", _fromImage.height()); + return subImage; + } + if (property == "scale") { + return _scale; + } + if (property == "isFacingAvatar") { + return _isFacingAvatar; + } + + return Base3DOverlay::getProperty(property); +} + void BillboardOverlay::setURL(const QString& url) { setBillboardURL(url); } diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index 018ca5f5cf..3a22a247f0 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -32,6 +32,7 @@ public: virtual void setProperties(const QScriptValue& properties); void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } + virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 144119c450..986088cebb 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -299,6 +299,45 @@ void Circle3DOverlay::setProperties(const QScriptValue &properties) { } } +QScriptValue Circle3DOverlay::getProperty(const QString& property) { + if (property == "startAt") { + return _startAt; + } + if (property == "endAt") { + return _endAt; + } + if (property == "outerRadius") { + return _outerRadius; + } + if (property == "innerRadius") { + return _innerRadius; + } + if (property == "hasTickMarks") { + return _hasTickMarks; + } + if (property == "majorTickMarksAngle") { + return _majorTickMarksAngle; + } + if (property == "minorTickMarksAngle") { + return _minorTickMarksAngle; + } + if (property == "majorTickMarksLength") { + return _majorTickMarksLength; + } + if (property == "minorTickMarksLength") { + return _minorTickMarksLength; + } + if (property == "majorTickMarksColor") { + return xColorToScriptValue(_scriptEngine, _majorTickMarksColor); + } + if (property == "minorTickMarksColor") { + return xColorToScriptValue(_scriptEngine, _minorTickMarksColor); + } + + return Planar3DOverlay::getProperty(property); +} + + bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index 191a0d3100..816ed280f9 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -21,6 +21,7 @@ public: ~Circle3DOverlay(); virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); float getStartAt() const { return _startAt; } float getEndAt() const { return _endAt; } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index c628199fe3..dee5d5d60a 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -116,3 +116,14 @@ void Grid3DOverlay::setProperties(const QScriptValue& properties) { _majorGridEvery = properties.property("majorGridEvery").toVariant().toInt(); } } + +QScriptValue Grid3DOverlay::getProperty(const QString& property) { + if (property == "minorGridWidth") { + return _minorGridWidth; + } + if (property == "majorGridEvery") { + return _majorGridEvery; + } + + return Base3DOverlay::getProperty(property); +} diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h index b1675f15d7..3e6a235d54 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ b/interface/src/ui/overlays/Grid3DOverlay.h @@ -33,6 +33,7 @@ public: virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); private: float _minorGridWidth; diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 18671ea074..896ebd1e68 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -79,3 +79,11 @@ void Line3DOverlay::setProperties(const QScriptValue& properties) { } } } + +QScriptValue Line3DOverlay::getProperty(const QString& property) { + if (property == "end" || property == "endPoint" || property == "p2") { + return vec3toScriptValue(_scriptEngine, _end); + } + + return Base3DOverlay::getProperty(property); +} diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index f9c4e0d6d6..0148648c35 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -28,6 +28,7 @@ public: void setEnd(const glm::vec3& end) { _end = end; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); protected: glm::vec3 _end; diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp index dcfc79f3b4..3ca79d548c 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp @@ -103,3 +103,14 @@ void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) { } } +QScriptValue LocalVoxelsOverlay::getProperty(const QString& property) { + if (property == "scale") { + return vec3toScriptValue(_scriptEngine, getDimensions()); + } + if (property == "name") { + return _treeName; + } + + return Volume3DOverlay::getProperty(property); +} + diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.h b/interface/src/ui/overlays/LocalVoxelsOverlay.h index 46a88407af..25ad4738b9 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.h +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.h @@ -38,7 +38,8 @@ public: virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); - + virtual QScriptValue getProperty(const QString& property); + private: static QMap _voxelSystemMap; // treeName/voxelSystem diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 150d40f15a..a2abfe77b1 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -14,6 +14,7 @@ ModelOverlay::ModelOverlay() : _model(), + _modelTextures(QVariantMap()), _scale(1.0f), _updateModel(false) { @@ -114,6 +115,8 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { QMetaObject::invokeMethod(&_model, "setTextureWithNameToURL", Qt::AutoConnection, Q_ARG(const QString&, key), Q_ARG(const QUrl&, newTextureURL)); + + _modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty() } } @@ -122,6 +125,34 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { } } +QScriptValue ModelOverlay::getProperty(const QString& property) { + if (property == "url") { + return _url.toString(); + } + if (property == "scale") { + return _scale; + } + if (property == "rotation") { + return quatToScriptValue(_scriptEngine, _rotation); + } + if (property == "dimensions") { + return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions()); + } + if (property == "textures") { + if (_modelTextures.size() > 0) { + QScriptValue textures = _scriptEngine->newObject(); + foreach(const QString& key, _modelTextures.keys()) { + textures.setProperty(key, _modelTextures[key].toString()); + } + return textures; + } else { + return QScriptValue(); + } + } + + return Base3DOverlay::getProperty(property); +} + bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 26471a79e1..c9f6799e8c 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -24,6 +24,7 @@ public: virtual void update(float deltatime); virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo) const; @@ -31,6 +32,7 @@ public: private: Model _model; + QVariantMap _modelTextures; QUrl _url; glm::quat _rotation; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 91a3a023f7..b2de7bdaad 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -77,6 +77,14 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) { } } +QScriptValue Planar3DOverlay::getProperty(const QString& property) { + if (property == "dimensions" || property == "scale" || property == "size") { + return vec2toScriptValue(_scriptEngine, _dimensions); + } + + Base3DOverlay::getProperty(property); +} + bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index ee4bb3e05a..fe73cfbe08 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -36,6 +36,7 @@ public: void setDimensions(const glm::vec2& value) { _dimensions = value; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index d8febbf0eb..ae21e4a8d4 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -179,4 +179,31 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) { } +QScriptValue Text3DOverlay::getProperty(const QString& property) { + if (property == "text") { + return _text; + } + if (property == "backgroundColor") { + return xColorToScriptValue(_scriptEngine, _backgroundColor); + } + if (property == "lineHeight") { + return _lineHeight; + } + if (property == "leftMargin") { + return _leftMargin; + } + if (property == "topMargin") { + return _topMargin; + } + if (property == "rightMargin") { + return _rightMargin; + } + if (property == "bottomMargin") { + return _bottomMargin; + } + if (property == "isFacingAvatar") { + return _isFacingAvatar; + } + return Planar3DOverlay::getProperty(property); +} diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 45e311c554..ff5575c20c 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -47,6 +47,7 @@ public: void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); private: void enableClipPlane(GLenum plane, float x, float y, float z, float w); diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index cc12d41e2e..0940caea04 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -85,6 +85,14 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { } } +QScriptValue Volume3DOverlay::getProperty(const QString& property) { + if (property == "dimensions" || property == "scale" || property == "size") { + return vec3toScriptValue(_scriptEngine, _dimensions); + } + + return Base3DOverlay::getProperty(property); +} + bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index 7cde169c30..8787759022 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -38,6 +38,7 @@ public: void setDimensions(const glm::vec3& value) { _dimensions = value; } virtual void setProperties(const QScriptValue& properties); + virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; From fac6b6b4267717c53b2270138bcfe2a715c4c532 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 12 Nov 2014 21:32:55 -0800 Subject: [PATCH 07/18] Refactor QRect conversion to QScriptValue --- interface/src/ui/overlays/BillboardOverlay.cpp | 7 +------ interface/src/ui/overlays/ImageOverlay.cpp | 7 +------ interface/src/ui/overlays/Overlay2D.cpp | 7 +------ libraries/shared/src/RegisteredMetaTypes.cpp | 18 ++++++++++++++++++ libraries/shared/src/RegisteredMetaTypes.h | 3 +++ 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 87b6dcc1c8..b36202cb04 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -162,12 +162,7 @@ QScriptValue BillboardOverlay::getProperty(const QString& property) { return _url; } if (property == "subImage") { - QScriptValue subImage = _scriptEngine->newObject(); - subImage.setProperty("x", _fromImage.x()); - subImage.setProperty("y", _fromImage.y()); - subImage.setProperty("width", _fromImage.width()); - subImage.setProperty("height", _fromImage.height()); - return subImage; + return qRectToScriptValue(_scriptEngine, _fromImage); } if (property == "scale") { return _scale; diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index f2e93c2e0e..615872e6ef 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -153,12 +153,7 @@ void ImageOverlay::setProperties(const QScriptValue& properties) { QScriptValue ImageOverlay::getProperty(const QString& property) { if (property == "subImage") { - QScriptValue subImage = _scriptEngine->newObject(); - subImage.setProperty("x", _fromImage.x()); - subImage.setProperty("y", _fromImage.y()); - subImage.setProperty("width", _fromImage.width()); - subImage.setProperty("height", _fromImage.height()); - return subImage; + return qRectToScriptValue(_scriptEngine, _fromImage); } if (property == "imageURL") { return _imageURL.toString(); diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index d71f8cac05..b7c0a3a3e4 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -67,12 +67,7 @@ void Overlay2D::setProperties(const QScriptValue& properties) { QScriptValue Overlay2D::getProperty(const QString& property) { if (property == "bounds") { - QScriptValue bounds = _scriptEngine->newObject(); - bounds.setProperty("x", _bounds.x()); - bounds.setProperty("y", _bounds.y()); - bounds.setProperty("width", _bounds.width()); - bounds.setProperty("height", _bounds.height()); - return bounds; + return qRectToScriptValue(_scriptEngine, _bounds); } if (property == "x") { return _bounds.x(); diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 5867e2ef43..02b9d5c927 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -30,6 +31,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); + qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue); qScriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue); qScriptRegisterMetaType(engine, qURLToScriptValue, qURLFromScriptValue); @@ -96,6 +98,22 @@ void quatFromScriptValue(const QScriptValue &object, glm::quat& quat) { quat.w = object.property("w").toVariant().toFloat(); } +QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect) { + QScriptValue obj = engine->newObject(); + obj.setProperty("x", rect.x()); + obj.setProperty("y", rect.y()); + obj.setProperty("width", rect.width()); + obj.setProperty("height", rect.height()); + return obj; +} + +void qRectFromScriptValue(const QScriptValue &object, QRect& rect) { + rect.setX(object.property("x").toVariant().toInt()); + rect.setY(object.property("y").toVariant().toInt()); + rect.setWidth(object.property("width").toVariant().toInt()); + rect.setHeight(object.property("height").toVariant().toInt()); +} + QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) { QScriptValue obj = engine->newObject(); obj.setProperty("red", color.red); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index b8884be845..0fd3138b06 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -42,6 +42,9 @@ void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2); QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat& quat); void quatFromScriptValue(const QScriptValue &object, glm::quat& quat); +QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect); +void qRectFromScriptValue(const QScriptValue& object, QRect& rect); + QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color); void xColorFromScriptValue(const QScriptValue &object, xColor& color); From f47620231e1f7d30a784119eb64e63ef74050628 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 16:16:20 -0800 Subject: [PATCH 08/18] Entities have user data --- libraries/entities/src/EntityItem.cpp | 7 +++++++ libraries/entities/src/EntityItem.h | 6 ++++++ libraries/entities/src/EntityItemProperties.cpp | 8 ++++++++ libraries/entities/src/EntityItemProperties.h | 10 +++++++++- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ef02aafbc8..8228ebc8ce 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -28,6 +28,7 @@ const float EntityItem::DEFAULT_GLOW_LEVEL = 0.0f; const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float EntityItem::DEFAULT_MASS = 1.0f; const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL; +const QString EntityItem::DEFAULT_USER_DATA = QString(""); const float EntityItem::DEFAULT_DAMPING = 0.5f; const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0); const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second @@ -71,6 +72,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _gravity = DEFAULT_GRAVITY; _damping = DEFAULT_DAMPING; _lifetime = DEFAULT_LIFETIME; + _userData = DEFAULT_USER_DATA; _registrationPoint = DEFAULT_REGISTRATION_POINT; _angularVelocity = DEFAULT_ANGULAR_VELOCITY; _angularDamping = DEFAULT_ANGULAR_DAMPING; @@ -115,6 +117,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_GRAVITY; requestedProperties += PROP_DAMPING; requestedProperties += PROP_LIFETIME; + requestedProperties += PROP_USER_DATA; requestedProperties += PROP_SCRIPT; requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_VELOCITY; @@ -231,6 +234,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); @@ -502,6 +506,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions); READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); + READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, _userData); if (wantDebug) { qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint; @@ -758,6 +763,7 @@ EntityItemProperties EntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignoreForCollisions, getIgnoreForCollisions); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove); COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData); properties._defaultSettings = false; @@ -794,6 +800,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions); SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index adf72198be..51accd2a4f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -196,6 +196,11 @@ public: static const float DEFAULT_LIFETIME; float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity + + /// User-specified data stored in a variant map + static const QString DEFAULT_USER_DATA; + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; } /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted bool isImmortal() const { return _lifetime == IMMORTAL; } @@ -284,6 +289,7 @@ protected: glm::vec3 _gravity; float _damping; float _lifetime; + QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0c184d5e35..86bf81f6e2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -37,6 +37,7 @@ EntityItemProperties::EntityItemProperties() : _gravity(EntityItem::DEFAULT_GRAVITY), _damping(EntityItem::DEFAULT_DAMPING), _lifetime(EntityItem::DEFAULT_LIFETIME), + _userData(EntityItem::DEFAULT_USER_DATA), _script(EntityItem::DEFAULT_SCRIPT), _registrationPoint(EntityItem::DEFAULT_REGISTRATION_POINT), _angularVelocity(EntityItem::DEFAULT_ANGULAR_VELOCITY), @@ -53,6 +54,7 @@ EntityItemProperties::EntityItemProperties() : _gravityChanged(false), _dampingChanged(false), _lifetimeChanged(false), + _userDataChanged(false), _scriptChanged(false), _registrationPointChanged(false), _angularVelocityChanged(false), @@ -198,6 +200,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GRAVITY, gravity); CHECK_PROPERTY_CHANGE(PROP_DAMPING, damping); CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime); + CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); @@ -247,6 +250,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(damping); COPY_PROPERTY_TO_QSCRIPTVALUE(mass); COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime); + COPY_PROPERTY_TO_QSCRIPTVALUE(userData); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(age, getAge()); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(script); @@ -350,6 +354,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(cutoff, setCutoff); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures); + COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData); _lastEdited = usecTimestampNow(); } @@ -512,6 +517,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, properties.getUserData()); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -722,6 +728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); return valid; } @@ -764,6 +771,7 @@ void EntityItemProperties::markAllChanged() { _gravityChanged = true; _dampingChanged = true; _lifetimeChanged = true; + _userDataChanged = true; _scriptChanged = true; _registrationPointChanged = true; _angularVelocityChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index d6b8181c28..534ed7615f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -47,6 +47,7 @@ enum EntityPropertyList { PROP_GRAVITY, PROP_DAMPING, PROP_LIFETIME, + PROP_USER_DATA, PROP_SCRIPT, // these properties are supported by some derived classes @@ -156,9 +157,13 @@ public: float getDamping() const { return _damping; } void setDamping(float value) { _damping = value; _dampingChanged = true; } - + float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; _lifetimeChanged = true; } /// set the lifetime in seconds for the entity + + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; _userDataChanged = true; } + float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } quint64 getCreated() const { return _created; } void setCreated(quint64 usecTime) { _created = usecTime; } @@ -216,6 +221,7 @@ public: bool gravityChanged() const { return _gravityChanged; } bool dampingChanged() const { return _dampingChanged; } bool lifetimeChanged() const { return _lifetimeChanged; } + bool userDataChanged() const { return _userDataChanged; } bool scriptChanged() const { return _scriptChanged; } bool dimensionsChanged() const { return _dimensionsChanged; } bool registrationPointChanged() const { return _registrationPointChanged; } @@ -315,6 +321,7 @@ private: glm::vec3 _gravity; float _damping; float _lifetime; + QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; @@ -331,6 +338,7 @@ private: bool _gravityChanged; bool _dampingChanged; bool _lifetimeChanged; + bool _userDataChanged; bool _scriptChanged; bool _registrationPointChanged; bool _angularVelocityChanged; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index a5fdd86e3d..e200d82e9d 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -75,7 +75,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS; + return VERSION_ENTITIES_HAVE_USER_DATA; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 466aebd36b..d617f2243a 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -125,6 +125,7 @@ const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3; const PacketVersion VERSION_ENTITIES_HAS_FILE_BREAKS = VERSION_ENTITIES_SUPPORT_SPLIT_MTU; const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4; const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5; +const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_VOXELS_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h From f8be98260cf87984c3bcbbe41de8c354f072d8e6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 16:32:15 -0800 Subject: [PATCH 09/18] String specific macros --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8228ebc8ce..a73bd486c9 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -506,7 +506,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions); READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); - READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, _userData); + READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData); if (wantDebug) { qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 86bf81f6e2..305507ead9 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -728,7 +728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData); return valid; } From 40576b3c03d03965d36cf87704f859578c335c68 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:02:45 -0800 Subject: [PATCH 10/18] moved append to the end --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a73bd486c9..e17bfb362a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -234,7 +234,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); - APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); @@ -243,6 +242,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove()); APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, From 9fc74515818357755512fe60b5124c29b68940bd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:06:57 -0800 Subject: [PATCH 11/18] Move macros to the end --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e17bfb362a..d5790d88a7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -117,7 +117,6 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_GRAVITY; requestedProperties += PROP_DAMPING; requestedProperties += PROP_LIFETIME; - requestedProperties += PROP_USER_DATA; requestedProperties += PROP_SCRIPT; requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_VELOCITY; @@ -126,6 +125,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_IGNORE_FOR_COLLISIONS; requestedProperties += PROP_COLLISIONS_WILL_MOVE; requestedProperties += PROP_LOCKED; + requestedProperties += PROP_USER_DATA; return requestedProperties; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 305507ead9..75fa05032a 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -200,7 +200,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GRAVITY, gravity); CHECK_PROPERTY_CHANGE(PROP_DAMPING, damping); CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime); - CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); @@ -226,6 +225,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_CUTOFF, cutoff); CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); + CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); return changedProperties; } @@ -250,7 +250,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(damping); COPY_PROPERTY_TO_QSCRIPTVALUE(mass); COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime); - COPY_PROPERTY_TO_QSCRIPTVALUE(userData); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(age, getAge()); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(script); @@ -280,6 +279,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(cutoff); COPY_PROPERTY_TO_QSCRIPTVALUE(locked); COPY_PROPERTY_TO_QSCRIPTVALUE(textures); + COPY_PROPERTY_TO_QSCRIPTVALUE(userData); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); From f914f02a0b39ad82f07f44a09802a72bb3b0b963 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:44:22 -0800 Subject: [PATCH 12/18] Move user data to end of enum --- libraries/entities/src/EntityItem.h | 11 +++++------ libraries/entities/src/EntityItemProperties.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 51accd2a4f..cb153dee60 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -196,11 +196,6 @@ public: static const float DEFAULT_LIFETIME; float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity - - /// User-specified data stored in a variant map - static const QString DEFAULT_USER_DATA; - const QString& getUserData() const { return _userData; } - void setUserData(const QString& value) { _userData = value; } /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted bool isImmortal() const { return _lifetime == IMMORTAL; } @@ -257,6 +252,10 @@ public: bool getLocked() const { return _locked; } void setLocked(bool value) { _locked = value; } + static const QString DEFAULT_USER_DATA; + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; } + // TODO: We need to get rid of these users of getRadius()... float getRadius() const; @@ -289,7 +288,6 @@ protected: glm::vec3 _gravity; float _damping; float _lifetime; - QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; @@ -298,6 +296,7 @@ protected: bool _ignoreForCollisions; bool _collisionsWillMove; bool _locked; + QString _userData; // NOTE: Radius support is obsolete, but these private helper functions are available for this class to // parse old data streams diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 534ed7615f..273aedb18a 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -47,7 +47,6 @@ enum EntityPropertyList { PROP_GRAVITY, PROP_DAMPING, PROP_LIFETIME, - PROP_USER_DATA, PROP_SCRIPT, // these properties are supported by some derived classes @@ -82,8 +81,9 @@ enum EntityPropertyList { // used by Model entities PROP_TEXTURES, PROP_ANIMATION_SETTINGS, + PROP_USER_DATA, - PROP_LAST_ITEM = PROP_ANIMATION_SETTINGS + PROP_LAST_ITEM = PROP_USER_DATA }; typedef PropertyFlags EntityPropertyFlags; From 6a4f1c857f3bcae8c8412b496b1a83c96a637fc6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 18:35:04 -0800 Subject: [PATCH 13/18] fix a couple bugs --- interface/src/renderer/Model.cpp | 8 ++++---- libraries/octree/src/OctreeElement.cpp | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index c007f44f2e..09aaa63929 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -537,7 +537,7 @@ void Model::renderSetup(RenderArgs* args) { } } - if (!_meshGroupsKnown) { + if (!_meshGroupsKnown && isLoadedWithTextures()) { segregateMeshGroups(); } } @@ -628,7 +628,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -649,7 +649,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -673,7 +673,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); } GLBATCH(glDepthMask)(true); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index a0a331beb3..32dafc0b68 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -1159,6 +1160,10 @@ OctreeElement* OctreeElement::addChildAtIndex(int childIndex) { bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) { bool deleteApproved = false; if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + qDebug() << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return deleteApproved; } From 5da0d1e55a287a965a8c7959d9f00fc7b62c3f2a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 20:53:31 -0800 Subject: [PATCH 14/18] fix regexs for dangerously deep recurssion suppression --- libraries/octree/src/Octree.cpp | 8 ++++---- libraries/octree/src/OctreeElement.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4450689949..93ee8c95d0 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -74,7 +74,7 @@ void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOp if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -96,7 +96,7 @@ void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctr if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithPostOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -126,7 +126,7 @@ void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, R if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperationDistanceSorted\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -167,7 +167,7 @@ bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOpe if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperator\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return false; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 32dafc0b68..e5db8b24f8 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1162,7 +1162,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "OctreeElement::safeDeepDeleteChildAtIndex\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return deleteApproved; From 744f9bc508960d45cd7f02b4f02c4b4c690754af Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 22:26:18 -0800 Subject: [PATCH 15/18] better handle corrupt packets that would cause unreasonably deep recursion --- libraries/octree/src/Octree.cpp | 52 ++++++++++++++++---------- libraries/octree/src/Octree.h | 2 +- libraries/octree/src/OctreeConstants.h | 3 +- libraries/octree/src/OctreeElement.h | 2 - 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 93ee8c95d0..e9cf1158fa 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -231,8 +231,18 @@ OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement, } // returns the element created! -OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach) { +OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount) { + + if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "Octree::createMissingElement\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + + qDebug() << "Octree::createMissingElement() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; + return lastParentElement; + } int indexOfNewChild = branchIndexWithDescendant(lastParentElement->getOctalCode(), codeToReach); + // If this parent element is a leaf, then you know the child path doesn't exist, so deal with // breaking up the leaf first, which will also create a child path if (lastParentElement->requiresSplit()) { @@ -246,7 +256,7 @@ OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, co if (*lastParentElement->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) { return lastParentElement->getChildAtIndex(indexOfNewChild); } else { - return createMissingElement(lastParentElement->getChildAtIndex(indexOfNewChild), codeToReach); + return createMissingElement(lastParentElement->getChildAtIndex(indexOfNewChild), codeToReach, recursionCount + 1); } } @@ -255,25 +265,20 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch int bytesLeftToRead = bytesAvailable; int bytesRead = 0; - bool wantDebug = false; // give this destination element the child mask from the packet const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; if ((size_t)bytesLeftToRead < sizeof(unsigned char)) { - if (wantDebug) { - qDebug() << "UNEXPECTED: readElementData() only had " << bytesLeftToRead << " bytes. " - "Not enough for meaningful data."; - } + qDebug() << "UNEXPECTED: readElementData() only had " << bytesLeftToRead << " bytes. " + "Not enough for meaningful data."; return bytesAvailable; // assume we read the entire buffer... } if (destinationElement->getScale() < SCALE_AT_DANGEROUSLY_DEEP_RECURSION) { - if (wantDebug) { - qDebug() << "UNEXPECTED: readElementData() destination element is unreasonably small [" - << destinationElement->getScale() * (float)TREE_SCALE << " meters] " - << " Discarding " << bytesAvailable << " remaining bytes."; - } + qDebug() << "UNEXPECTED: readElementData() destination element is unreasonably small [" + << destinationElement->getScale() * (float)TREE_SCALE << " meters] " + << " Discarding " << bytesAvailable << " remaining bytes."; return bytesAvailable; // assume we read the entire buffer... } @@ -322,7 +327,7 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch : sizeof(childInBufferMask); if (bytesLeftToRead < bytesForMasks) { - if (wantDebug) { + if (bytesLeftToRead > 0) { qDebug() << "UNEXPECTED: readElementDataFromBuffer() only had " << bytesLeftToRead << " bytes before masks. " "Not enough for meaningful data."; } @@ -385,7 +390,6 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long ReadBitstreamToTreeParams& args) { int bytesRead = 0; const unsigned char* bitstreamAt = bitstream; - bool wantDebug = false; // If destination element is not included, set it to root if (!args.destinationElement) { @@ -398,14 +402,24 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long while (bitstreamAt < bitstream + bufferSizeBytes) { OctreeElement* bitstreamRootElement = nodeForOctalCode(args.destinationElement, (unsigned char *)bitstreamAt, NULL); - int numberOfThreeBitSectionsInStream = numberOfThreeBitSectionsInCode(bitstreamAt, bufferSizeBytes); + if (numberOfThreeBitSectionsInStream > UNREASONABLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... " + "numberOfThreeBitSectionsInStream: \\d+ This buffer is corrupt. Returning." + ); + + + qDebug() << "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... " + "numberOfThreeBitSectionsInStream:" << numberOfThreeBitSectionsInStream << + "This buffer is corrupt. Returning."; + return; + } if (numberOfThreeBitSectionsInStream == OVERFLOWED_OCTCODE_BUFFER) { - if (wantDebug) { - qDebug() << "UNEXPECTED: parsing of the octal code would overflow the buffer. " - "This buffer is corrupt. Returning."; - } + qDebug() << "UNEXPECTED: parsing of the octal code would overflow the buffer. " + "This buffer is corrupt. Returning."; return; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 42cbb3c38d..4ac7e22d90 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -373,7 +373,7 @@ protected: static bool countOctreeElementsOperation(OctreeElement* element, void* extraData); OctreeElement* nodeForOctalCode(OctreeElement* ancestorElement, const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const; - OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach); + OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount = 0); int readElementData(OctreeElement *destinationElement, const unsigned char* nodeData, int bufferSizeBytes, ReadBitstreamToTreeParams& args); diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 4186b90888..e924676771 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -35,10 +35,11 @@ const int MAX_TREE_SLICE_BYTES = 26; const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f; // These are guards to prevent our voxel tree recursive routines from spinning out of control -const int UNREASONABLY_DEEP_RECURSION = 20; // use this for something that you want to be shallow, but not spin out +const int UNREASONABLY_DEEP_RECURSION = 29; // use this for something that you want to be shallow, but not spin out const int DANGEROUSLY_DEEP_RECURSION = 200; // use this for something that needs to go deeper const float SCALE_AT_UNREASONABLY_DEEP_RECURSION = (1.0f / powf(2.0f, UNREASONABLY_DEEP_RECURSION)); const float SCALE_AT_DANGEROUSLY_DEEP_RECURSION = (1.0f / powf(2.0f, DANGEROUSLY_DEEP_RECURSION)); +const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = SCALE_AT_UNREASONABLY_DEEP_RECURSION * 2.0f; // 0.00006103515 meter ~1/10,0000th const int DEFAULT_MAX_OCTREE_PPS = 600; // the default maximum PPS we think any octree based server should send to a client diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 31a9dfddc1..2bd5e3ae1e 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -36,8 +36,6 @@ class ReadBitstreamToTreeParams; class Shape; class VoxelSystem; -const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = (1.0f / TREE_SCALE) / 10000.0f; // 1/10,000th of a meter - // Callers who want delete hook callbacks should implement this class class OctreeElementDeleteHook { public: From 7b69642c67a301e5d75f94b8700dd0e66057f17e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 23:03:12 -0800 Subject: [PATCH 16/18] fix bug in animation jitter on turn --- libraries/entities/src/ModelEntityItem.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 52b8f7e643..f50fe7866b 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -115,7 +115,9 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying); if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { - setAnimationIsPlaying(animationIsPlaying); + if (animationIsPlaying != getAnimationIsPlaying()) { + setAnimationIsPlaying(animationIsPlaying); + } } if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { setAnimationFPS(animationFPS); @@ -345,7 +347,6 @@ QVector ModelEntityItem::getAnimationFrame() { if (frameCount > 0) { int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; - if (animationFrameIndex < 0 || animationFrameIndex > frameCount) { animationFrameIndex = 0; } @@ -427,7 +428,9 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { if (settingsMap.contains("running")) { bool running = settingsMap["running"].toBool(); - setAnimationIsPlaying(running); + if (running != getAnimationIsPlaying()) { + setAnimationIsPlaying(running); + } } if (settingsMap.contains("firstFrame")) { From 5ba213f8d191cc07fc2febe88a0eb783d9635fd6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 14 Nov 2014 09:33:11 -0800 Subject: [PATCH 17/18] fix for function override with no return --- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index b2de7bdaad..ffd7d73531 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -82,7 +82,7 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { return vec2toScriptValue(_scriptEngine, _dimensions); } - Base3DOverlay::getProperty(property); + return Base3DOverlay::getProperty(property); } bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, From 20fdd6d8117405296b02e7a383630dc95aab0ae4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 14 Nov 2014 10:31:30 -0800 Subject: [PATCH 18/18] Disable model overlay properties example It causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() --- examples/overlaysExample.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 3ab70a0562..0d47f7ca64 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -194,20 +194,23 @@ print("Cube overlay color =\n" + "green: " + cubeColor.green + "\n" + "blue: " + cubeColor.blue ); -var modelOverlayProperties = { - textures: { - filename1: "http://url1", - filename2: "http://url2" - } -} -var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); -var textures = Overlays.getProperty(modelOverlay, "textures"); -var textureValues = ""; -for (key in textures) { - textureValues += "\n" + key + ": " + textures[key]; -} -print("Model overlay textures =" + textureValues); -Overlays.deleteOverlay(modelOverlay); + +// This model overlay example causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() +//var modelOverlayProperties = { +// textures: { +// filename1: HIFI_PUBLIC_BUCKET + "images/testing-swatches.svg", +// filename2: HIFI_PUBLIC_BUCKET + "images/hifi-interface-tools.svg" +// } +//} +//var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); +//var textures = Overlays.getProperty(modelOverlay, "textures"); +//var textureValues = ""; +//for (key in textures) { +// textureValues += "\n" + key + ": " + textures[key]; +//} +//print("Model overlay textures =" + textureValues); +//Overlays.deleteOverlay(modelOverlay); + print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined // When our script shuts down, we should clean up all of our overlays