From 0cd60782e79c5c7a9784efc324626c1dfacc1bd1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 May 2015 11:00:30 -0700 Subject: [PATCH 01/19] Add error handling to JSConsole --- interface/src/ui/JSConsole.cpp | 5 +++++ interface/src/ui/JSConsole.h | 1 + 2 files changed, 6 insertions(+) diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 700781df69..74585df855 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -59,6 +59,7 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : connect(_scriptEngine, SIGNAL(evaluationFinished(QScriptValue, bool)), this, SLOT(handleEvalutationFinished(QScriptValue, bool))); connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); + connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&))); resizeTextInput(); } @@ -96,6 +97,10 @@ void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) appendMessage(gutter, resultStr); } +void JSConsole::handleError(const QString& message) { + appendMessage(GUTTER_ERROR, "" + message.toHtmlEscaped() + ""); +} + void JSConsole::handlePrint(const QString& message) { appendMessage("", message); } diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index daeba8ea15..98afdf7bf8 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -49,6 +49,7 @@ protected slots: void resizeTextInput(); void handleEvalutationFinished(QScriptValue result, bool isException); void handlePrint(const QString& message); + void handleError(const QString& message); private: void appendMessage(const QString& gutter, const QString& message); From 5d9f62066a31ac787bced47dad231432823882d4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 May 2015 10:27:22 -0700 Subject: [PATCH 02/19] reload the merged config after making versioned changes --- domain-server/src/DomainServerSettingsManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c0d85687bb..5cd5b5ef35 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -104,6 +104,9 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // write the new settings to the json file persistToFile(); + + // reload the master and user config so that the merged config is right + _configMap.loadMasterAndUserConfig(argumentList); } } } From 33545a0c3f81f2a7ac3c35f94103256ca6f2cfd6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 May 2015 13:45:50 -0700 Subject: [PATCH 03/19] fix for domain-server settings account disconnect --- domain-server/resources/web/settings/js/settings.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index 450d686cd4..3ef69d817b 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -254,12 +254,15 @@ $(document).ready(function(){ }); $('#' + Settings.FORM_ID).on('click', '#' + Settings.DISCONNECT_ACCOUNT_BTN_ID, function(e){ + $(this).blur(); disonnectHighFidelityAccount(); + e.preventDefault(); }); $('#' + Settings.FORM_ID).on('click', '#' + Settings.CONNECT_ACCOUNT_BTN_ID, function(e){ $(this).blur(); prepareAccessTokenPrompt(); + e.preventDefault(); }); var panelsSource = $('#panels-template').html() @@ -345,7 +348,7 @@ function disonnectHighFidelityAccount() { + "

This could cause your domain to appear offline and no longer be reachable via any place names.", type: "warning", html: true, - showCancelButton: true, + showCancelButton: true }, function(){ // we need to post to settings to clear the access-token $(Settings.ACCESS_TOKEN_SELECTOR).val('').change(); From 8a0c1cab1e2cb7e4bb65912de809b74717974eea Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 21 May 2015 15:31:30 -0700 Subject: [PATCH 04/19] inspect now uses accurate picking and camera slerps to looks at target. pointer does not show u when user is inspecting --- examples/defaultScripts.js | 1 + examples/inspect.js | 424 ++++++++++++++++++++----------------- examples/pointer.js | 114 ++++++---- 3 files changed, 301 insertions(+), 238 deletions(-) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 89d4094856..ff22f68cb5 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -18,3 +18,4 @@ Script.load("notifications.js"); Script.load("look.js"); Script.load("users.js"); Script.load("grab.js"); +Script.load("pointer.js"); diff --git a/examples/inspect.js b/examples/inspect.js index d730a7e53f..e1f941497b 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -25,8 +25,18 @@ var ALTITUDE_RATE = 200.0; var RADIUS_RATE = 1.0 / 100.0; var PAN_RATE = 50.0; -var Y_AXIS = { x: 0, y: 1, z: 0 }; -var X_AXIS = { x: 1, y: 0, z: 0 }; +var Y_AXIS = { + x: 0, + y: 1, + z: 0 +}; +var X_AXIS = { + x: 1, + y: 0, + z: 0 +}; + +var LOOK_AT_TIME = 500; var alt = false; var shift = false; @@ -46,9 +56,21 @@ var mouseLastX = 0; var mouseLastY = 0; -var center = { x: 0, y: 0, z: 0 }; -var position = { x: 0, y: 0, z: 0 }; -var vector = { x: 0, y: 0, z: 0 }; +var center = { + x: 0, + y: 0, + z: 0 +}; +var position = { + x: 0, + y: 0, + z: 0 +}; +var vector = { + x: 0, + y: 0, + z: 0 +}; var radius = 0.0; var azimuth = 0.0; var altitude = 0.0; @@ -56,244 +78,262 @@ var altitude = 0.0; var avatarPosition; var avatarOrientation; +var rotatingTowardsTarget = false; +var targetCamOrientation; +var oldPosition, oldOrientation; + function orientationOf(vector) { - var direction, - yaw, - pitch; + var direction, + yaw, + pitch; - direction = Vec3.normalize(vector); - yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); - pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); - return Quat.multiply(yaw, pitch); + direction = Vec3.normalize(vector); + yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); + pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); + return Quat.multiply(yaw, pitch); } function handleRadialMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - radius += radius * dy * RADIUS_RATE; - if (radius < 1) { - radius = 1; - } - - vector = { x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, - y: Math.sin(altitude) * radius, - z: (Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + radius += radius * dy * RADIUS_RATE; + if (radius < 1) { + radius = 1; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handleOrbitMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - altitude += dy / ALTITUDE_RATE; - if (altitude > PI / 2.0) { - altitude = PI / 2.0; - } - if (altitude < -PI / 2.0) { - altitude = -PI / 2.0; - } - - vector = { x:(Math.cos(altitude) * Math.cos(azimuth)) * radius, - y:Math.sin(altitude) * radius, - z:(Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + altitude += dy / ALTITUDE_RATE; + if (altitude > PI / 2.0) { + altitude = PI / 2.0; + } + if (altitude < -PI / 2.0) { + altitude = -PI / 2.0; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handlePanMode(dx, dy) { - var up = Quat.getUp(Camera.getOrientation()); - var right = Quat.getRight(Camera.getOrientation()); - var distance = Vec3.length(vector); - - var dv = Vec3.sum(Vec3.multiply(up, - distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); - - center = Vec3.sum(center, dv); - position = Vec3.sum(position, dv); - - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + var up = Quat.getUp(Camera.getOrientation()); + var right = Quat.getRight(Camera.getOrientation()); + var distance = Vec3.length(vector); + + var dv = Vec3.sum(Vec3.multiply(up, -distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); + + center = Vec3.sum(center, dv); + position = Vec3.sum(position, dv); + + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function saveCameraState() { - oldMode = Camera.mode; - var oldPosition = Camera.getPosition(); - Camera.mode = "independent"; - Camera.setPosition(oldPosition); + oldMode = Camera.mode; + oldPosition = Camera.getPosition(); + oldOrientation = Camera.getOrientation(); + + Camera.mode = "independent"; + Camera.setPosition(oldPosition); } function restoreCameraState() { - Camera.mode = oldMode; + Camera.mode = oldMode; + Camera.setPosition(oldPosition); + Camera.setOrientation(oldOrientation); } function handleModes() { - var newMode = (mode == noMode) ? noMode : detachedMode; - if (alt) { - if (control) { - if (shift) { - newMode = panningMode; - } else { - newMode = orbitMode; - } - } else { - newMode = radialMode; - } - } - - // if entering detachMode - if (newMode == detachedMode && mode != detachedMode) { - avatarPosition = MyAvatar.position; - avatarOrientation = MyAvatar.orientation; - } - // if leaving detachMode - if (mode == detachedMode && newMode == detachedMode && - (avatarPosition.x != MyAvatar.position.x || - avatarPosition.y != MyAvatar.position.y || - avatarPosition.z != MyAvatar.position.z || - avatarOrientation.x != MyAvatar.orientation.x || - avatarOrientation.y != MyAvatar.orientation.y || - avatarOrientation.z != MyAvatar.orientation.z || - avatarOrientation.w != MyAvatar.orientation.w)) { - newMode = noMode; + var newMode = (mode == noMode) ? noMode : detachedMode; + if (alt) { + if (control) { + if (shift) { + newMode = panningMode; + } else { + newMode = orbitMode; + } + } else { + newMode = radialMode; } + } - if (mode == noMode && newMode != noMode && Camera.mode == "independent") { - newMode = noMode; - } + // if entering detachMode + if (newMode == detachedMode && mode != detachedMode) { + avatarPosition = MyAvatar.position; + avatarOrientation = MyAvatar.orientation; + } + // if leaving detachMode + if (mode == detachedMode && newMode == detachedMode && + (avatarPosition.x != MyAvatar.position.x || + avatarPosition.y != MyAvatar.position.y || + avatarPosition.z != MyAvatar.position.z || + avatarOrientation.x != MyAvatar.orientation.x || + avatarOrientation.y != MyAvatar.orientation.y || + avatarOrientation.z != MyAvatar.orientation.z || + avatarOrientation.w != MyAvatar.orientation.w)) { + newMode = noMode; + } - // if leaving noMode - if (mode == noMode && newMode != noMode) { - saveCameraState(); - } - // if entering noMode - if (newMode == noMode && mode != noMode) { - restoreCameraState(); - } - - mode = newMode; + if (mode == noMode && newMode != noMode && Camera.mode == "independent") { + newMode = noMode; + } + + // if leaving noMode + if (mode == noMode && newMode != noMode) { + saveCameraState(); + } + // if entering noMode + if (newMode == noMode && mode != noMode) { + restoreCameraState(); + } + + mode = newMode; } function keyPressEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = true; - changed = true; - } - if (event.text == "CONTROL") { - control = true; - changed = true; - } - if (event.text == "SHIFT") { - shift = true; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = true; + changed = true; + } + if (event.text == "CONTROL") { + control = true; + changed = true; + } + if (event.text == "SHIFT") { + shift = true; + changed = true; + } + + if (changed) { + handleModes(); + } } function keyReleaseEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = false; - changed = true; - } - if (event.text == "CONTROL") { - control = false; - changed = true; - } - if (event.text == "SHIFT") { - shift = false; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = false; + changed = true; + mode = noMode; + restoreCameraState(); + } + if (event.text == "CONTROL") { + control = false; + changed = true; + } + if (event.text == "SHIFT") { + shift = false; + changed = true; + } + + if (changed) { + handleModes(); + } } function mousePressEvent(event) { - if (alt && !isActive) { - mouseLastX = event.x; - mouseLastY = event.y; - - // Compute trajectories related values - var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); - var modelIntersection = Entities.findRayIntersection(pickRay); - - position = Camera.getPosition(); - - var avatarTarget = MyAvatar.getTargetAvatarPosition(); - - - var distance = -1; - var string; - - if (modelIntersection.intersects && modelIntersection.accurate) { - distance = modelIntersection.distance; - center = modelIntersection.properties.position; - string = "Inspecting model"; - } - - if ((distance == -1 || Vec3.length(Vec3.subtract(avatarTarget, position)) < distance) && - (avatarTarget.x != 0 || avatarTarget.y != 0 || avatarTarget.z != 0)) { - distance = Vec3.length(Vec3.subtract(avatarTarget, position)); - center = avatarTarget; - string = "Inspecting avatar"; - } - - if (distance == -1) { - return; - } - - vector = Vec3.subtract(position, center); - radius = Vec3.length(vector); - azimuth = Math.atan2(vector.z, vector.x); - altitude = Math.asin(vector.y / Vec3.length(vector)); - - print(string); - isActive = true; + if (alt && !isActive) { + mouseLastX = event.x; + mouseLastY = event.y; + + // Compute trajectories related values + var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); + var modelIntersection = Entities.findRayIntersection(pickRay, true); + + position = Camera.getPosition(); + + var avatarTarget = MyAvatar.getTargetAvatarPosition(); + + + var distance = -1; + var string; + + if (modelIntersection.intersects && modelIntersection.accurate) { + distance = modelIntersection.distance; + center = modelIntersection.intersection; + string = "Inspecting model"; + //We've selected our target, now orbit towards it automatically + rotatingTowardsTarget = true; + //calculate our target cam rotation + Script.setTimeout(function() { + rotatingTowardsTarget = false; + }, LOOK_AT_TIME); + + vector = Vec3.subtract(position, center); + targetCamOrientation = orientationOf(vector); + radius = Vec3.length(vector); + azimuth = Math.atan2(vector.z, vector.x); + altitude = Math.asin(vector.y / Vec3.length(vector)); + + isActive = true; } + + } } function mouseReleaseEvent(event) { - if (isActive) { - isActive = false; - } + if (isActive) { + isActive = false; + } } function mouseMoveEvent(event) { - if (isActive && mode != noMode) { - if (mode == radialMode) { - handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == orbitMode) { - handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == panningMode) { - handlePanMode(event.x - mouseLastX, event.y - mouseLastY); - } - - mouseLastX = event.x; - mouseLastY = event.y; + if (isActive && mode != noMode && !rotatingTowardsTarget) { + if (mode == radialMode) { + handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); } + if (mode == orbitMode) { + handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); + } + if (mode == panningMode) { + handlePanMode(event.x - mouseLastX, event.y - mouseLastY); + } + + } + mouseLastX = event.x; + mouseLastY = event.y; } function update() { - handleModes(); + handleModes(); + if (rotatingTowardsTarget) { + rotateTowardsTarget(); + } +} + +function rotateTowardsTarget() { + var newOrientation = Quat.mix(Camera.getOrientation(), targetCamOrientation, .1); + Camera.setOrientation(newOrientation); } function scriptEnding() { - if (mode != noMode) { - restoreCameraState(); - } + if (mode != noMode) { + restoreCameraState(); + } } Controller.keyPressEvent.connect(keyPressEvent); diff --git a/examples/pointer.js b/examples/pointer.js index dfb79569f7..cdfb93f2d3 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -1,77 +1,99 @@ - var lineEntityID = null; var lineIsRezzed = false; - +var altHeld = false; +var lineCreated = false; function nearLinePoint(targetPosition) { - var handPosition = MyAvatar.getRightPalmPosition(); - var along = Vec3.subtract(targetPosition, handPosition); - along = Vec3.normalize(along); - along = Vec3.multiply(along, 0.4); - return Vec3.sum(handPosition, along); + var handPosition = MyAvatar.getRightPalmPosition(); + var along = Vec3.subtract(targetPosition, handPosition); + along = Vec3.normalize(along); + along = Vec3.multiply(along, 0.4); + return Vec3.sum(handPosition, along); } function removeLine() { - if (lineIsRezzed) { - Entities.deleteEntity(lineEntityID); - lineEntityID = null; - lineIsRezzed = false; - } + if (lineIsRezzed) { + Entities.deleteEntity(lineEntityID); + lineEntityID = null; + lineIsRezzed = false; + } } function createOrUpdateLine(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking - var props = Entities.getEntityProperties(intersection.entityID); + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking + var props = Entities.getEntityProperties(intersection.entityID); - if (intersection.intersects) { - var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)); - if (lineIsRezzed) { - Entities.editEntity(lineEntityID, { - position: nearLinePoint(intersection.intersection), - dimensions: dim, - lifetime: 15 + props.lifespan // renew lifetime - }); - } else { - lineIsRezzed = true; - lineEntityID = Entities.addEntity({ - type: "Line", - position: nearLinePoint(intersection.intersection), - dimensions: dim, - color: { red: 255, green: 255, blue: 255 }, - lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. - }); - } + if (intersection.intersects) { + var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)); + if (lineIsRezzed) { + Entities.editEntity(lineEntityID, { + position: nearLinePoint(intersection.intersection), + dimensions: dim, + lifetime: 15 + props.lifespan // renew lifetime + }); } else { - removeLine(); + lineIsRezzed = true; + lineEntityID = Entities.addEntity({ + type: "Line", + position: nearLinePoint(intersection.intersection), + dimensions: dim, + color: { + red: 255, + green: 255, + blue: 255 + }, + lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. + }); } + } else { + removeLine(); + } } function mousePressEvent(event) { - if (!event.isLeftButton) { - return; - } - Controller.mouseMoveEvent.connect(mouseMoveEvent); - createOrUpdateLine(event); - } + if (!event.isLeftButton || altHeld) { + return; + } + Controller.mouseMoveEvent.connect(mouseMoveEvent); + createOrUpdateLine(event); + lineCreated = true; +} function mouseMoveEvent(event) { - createOrUpdateLine(event); + createOrUpdateLine(event); } function mouseReleaseEvent(event) { - if (!event.isLeftButton) { - return; - } - Controller.mouseMoveEvent.disconnect(mouseMoveEvent); - removeLine(); + if (!lineCreated) { + return; + } + Controller.mouseMoveEvent.disconnect(mouseMoveEvent); + removeLine(); + lineCreated = false; +} + +function keyPressEvent(event) { + if (event.text == "ALT") { + altHeld = true; + } +} + +function keyReleaseEvent(event) { + if (event.text == "ALT") { + altHeld = false; + } + } Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); \ No newline at end of file From ce1ccf1c405ab17e69e73e0c4cf16e7d2acbdceb Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 21 May 2015 18:08:04 -0700 Subject: [PATCH 05/19] added oldMode as global vairable --- examples/inspect.js | 425 ++++++++++++++++++++++++-------------------- 1 file changed, 233 insertions(+), 192 deletions(-) diff --git a/examples/inspect.js b/examples/inspect.js index d730a7e53f..0df90fbac3 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -25,8 +25,18 @@ var ALTITUDE_RATE = 200.0; var RADIUS_RATE = 1.0 / 100.0; var PAN_RATE = 50.0; -var Y_AXIS = { x: 0, y: 1, z: 0 }; -var X_AXIS = { x: 1, y: 0, z: 0 }; +var Y_AXIS = { + x: 0, + y: 1, + z: 0 +}; +var X_AXIS = { + x: 1, + y: 0, + z: 0 +}; + +var LOOK_AT_TIME = 500; var alt = false; var shift = false; @@ -34,6 +44,7 @@ var control = false; var isActive = false; +var oldMode = Camera.mode; var noMode = 0; var orbitMode = 1; var radialMode = 2; @@ -46,9 +57,21 @@ var mouseLastX = 0; var mouseLastY = 0; -var center = { x: 0, y: 0, z: 0 }; -var position = { x: 0, y: 0, z: 0 }; -var vector = { x: 0, y: 0, z: 0 }; +var center = { + x: 0, + y: 0, + z: 0 +}; +var position = { + x: 0, + y: 0, + z: 0 +}; +var vector = { + x: 0, + y: 0, + z: 0 +}; var radius = 0.0; var azimuth = 0.0; var altitude = 0.0; @@ -56,244 +79,262 @@ var altitude = 0.0; var avatarPosition; var avatarOrientation; +var rotatingTowardsTarget = false; +var targetCamOrientation; +var oldPosition, oldOrientation; + function orientationOf(vector) { - var direction, - yaw, - pitch; + var direction, + yaw, + pitch; - direction = Vec3.normalize(vector); - yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); - pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); - return Quat.multiply(yaw, pitch); + direction = Vec3.normalize(vector); + yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); + pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); + return Quat.multiply(yaw, pitch); } function handleRadialMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - radius += radius * dy * RADIUS_RATE; - if (radius < 1) { - radius = 1; - } - - vector = { x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, - y: Math.sin(altitude) * radius, - z: (Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + radius += radius * dy * RADIUS_RATE; + if (radius < 1) { + radius = 1; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handleOrbitMode(dx, dy) { - azimuth += dx / AZIMUTH_RATE; - altitude += dy / ALTITUDE_RATE; - if (altitude > PI / 2.0) { - altitude = PI / 2.0; - } - if (altitude < -PI / 2.0) { - altitude = -PI / 2.0; - } - - vector = { x:(Math.cos(altitude) * Math.cos(azimuth)) * radius, - y:Math.sin(altitude) * radius, - z:(Math.cos(altitude) * Math.sin(azimuth)) * radius }; - position = Vec3.sum(center, vector); - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + azimuth += dx / AZIMUTH_RATE; + altitude += dy / ALTITUDE_RATE; + if (altitude > PI / 2.0) { + altitude = PI / 2.0; + } + if (altitude < -PI / 2.0) { + altitude = -PI / 2.0; + } + + vector = { + x: (Math.cos(altitude) * Math.cos(azimuth)) * radius, + y: Math.sin(altitude) * radius, + z: (Math.cos(altitude) * Math.sin(azimuth)) * radius + }; + position = Vec3.sum(center, vector); + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function handlePanMode(dx, dy) { - var up = Quat.getUp(Camera.getOrientation()); - var right = Quat.getRight(Camera.getOrientation()); - var distance = Vec3.length(vector); - - var dv = Vec3.sum(Vec3.multiply(up, - distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); - - center = Vec3.sum(center, dv); - position = Vec3.sum(position, dv); - - Camera.setPosition(position); - Camera.setOrientation(orientationOf(vector)); + var up = Quat.getUp(Camera.getOrientation()); + var right = Quat.getRight(Camera.getOrientation()); + var distance = Vec3.length(vector); + + var dv = Vec3.sum(Vec3.multiply(up, -distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); + + center = Vec3.sum(center, dv); + position = Vec3.sum(position, dv); + + Camera.setPosition(position); + Camera.setOrientation(orientationOf(vector)); } function saveCameraState() { - oldMode = Camera.mode; - var oldPosition = Camera.getPosition(); - Camera.mode = "independent"; - Camera.setPosition(oldPosition); + oldMode = Camera.mode; + oldPosition = Camera.getPosition(); + oldOrientation = Camera.getOrientation(); + + Camera.mode = "independent"; + Camera.setPosition(oldPosition); } function restoreCameraState() { - Camera.mode = oldMode; + Camera.mode = oldMode; + Camera.setPosition(oldPosition); + Camera.setOrientation(oldOrientation); } function handleModes() { - var newMode = (mode == noMode) ? noMode : detachedMode; - if (alt) { - if (control) { - if (shift) { - newMode = panningMode; - } else { - newMode = orbitMode; - } - } else { - newMode = radialMode; - } - } - - // if entering detachMode - if (newMode == detachedMode && mode != detachedMode) { - avatarPosition = MyAvatar.position; - avatarOrientation = MyAvatar.orientation; - } - // if leaving detachMode - if (mode == detachedMode && newMode == detachedMode && - (avatarPosition.x != MyAvatar.position.x || - avatarPosition.y != MyAvatar.position.y || - avatarPosition.z != MyAvatar.position.z || - avatarOrientation.x != MyAvatar.orientation.x || - avatarOrientation.y != MyAvatar.orientation.y || - avatarOrientation.z != MyAvatar.orientation.z || - avatarOrientation.w != MyAvatar.orientation.w)) { - newMode = noMode; + var newMode = (mode == noMode) ? noMode : detachedMode; + if (alt) { + if (control) { + if (shift) { + newMode = panningMode; + } else { + newMode = orbitMode; + } + } else { + newMode = radialMode; } + } - if (mode == noMode && newMode != noMode && Camera.mode == "independent") { - newMode = noMode; - } + // if entering detachMode + if (newMode == detachedMode && mode != detachedMode) { + avatarPosition = MyAvatar.position; + avatarOrientation = MyAvatar.orientation; + } + // if leaving detachMode + if (mode == detachedMode && newMode == detachedMode && + (avatarPosition.x != MyAvatar.position.x || + avatarPosition.y != MyAvatar.position.y || + avatarPosition.z != MyAvatar.position.z || + avatarOrientation.x != MyAvatar.orientation.x || + avatarOrientation.y != MyAvatar.orientation.y || + avatarOrientation.z != MyAvatar.orientation.z || + avatarOrientation.w != MyAvatar.orientation.w)) { + newMode = noMode; + } - // if leaving noMode - if (mode == noMode && newMode != noMode) { - saveCameraState(); - } - // if entering noMode - if (newMode == noMode && mode != noMode) { - restoreCameraState(); - } - - mode = newMode; + if (mode == noMode && newMode != noMode && Camera.mode == "independent") { + newMode = noMode; + } + + // if leaving noMode + if (mode == noMode && newMode != noMode) { + saveCameraState(); + } + // if entering noMode + if (newMode == noMode && mode != noMode) { + restoreCameraState(); + } + + mode = newMode; } function keyPressEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = true; - changed = true; - } - if (event.text == "CONTROL") { - control = true; - changed = true; - } - if (event.text == "SHIFT") { - shift = true; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = true; + changed = true; + } + if (event.text == "CONTROL") { + control = true; + changed = true; + } + if (event.text == "SHIFT") { + shift = true; + changed = true; + } + + if (changed) { + handleModes(); + } } function keyReleaseEvent(event) { - var changed = false; - - if (event.text == "ALT") { - alt = false; - changed = true; - } - if (event.text == "CONTROL") { - control = false; - changed = true; - } - if (event.text == "SHIFT") { - shift = false; - changed = true; - } - - if (changed) { - handleModes(); - } + var changed = false; + + if (event.text == "ALT") { + alt = false; + changed = true; + mode = noMode; + restoreCameraState(); + } + if (event.text == "CONTROL") { + control = false; + changed = true; + } + if (event.text == "SHIFT") { + shift = false; + changed = true; + } + + if (changed) { + handleModes(); + } } function mousePressEvent(event) { - if (alt && !isActive) { - mouseLastX = event.x; - mouseLastY = event.y; - - // Compute trajectories related values - var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); - var modelIntersection = Entities.findRayIntersection(pickRay); - - position = Camera.getPosition(); - - var avatarTarget = MyAvatar.getTargetAvatarPosition(); - - - var distance = -1; - var string; - - if (modelIntersection.intersects && modelIntersection.accurate) { - distance = modelIntersection.distance; - center = modelIntersection.properties.position; - string = "Inspecting model"; - } - - if ((distance == -1 || Vec3.length(Vec3.subtract(avatarTarget, position)) < distance) && - (avatarTarget.x != 0 || avatarTarget.y != 0 || avatarTarget.z != 0)) { - distance = Vec3.length(Vec3.subtract(avatarTarget, position)); - center = avatarTarget; - string = "Inspecting avatar"; - } - - if (distance == -1) { - return; - } - - vector = Vec3.subtract(position, center); - radius = Vec3.length(vector); - azimuth = Math.atan2(vector.z, vector.x); - altitude = Math.asin(vector.y / Vec3.length(vector)); - - print(string); - isActive = true; + if (alt && !isActive) { + mouseLastX = event.x; + mouseLastY = event.y; + + // Compute trajectories related values + var pickRay = Camera.computePickRay(mouseLastX, mouseLastY); + var modelIntersection = Entities.findRayIntersection(pickRay, true); + + position = Camera.getPosition(); + + var avatarTarget = MyAvatar.getTargetAvatarPosition(); + + + var distance = -1; + var string; + + if (modelIntersection.intersects && modelIntersection.accurate) { + distance = modelIntersection.distance; + center = modelIntersection.intersection; + string = "Inspecting model"; + //We've selected our target, now orbit towards it automatically + rotatingTowardsTarget = true; + //calculate our target cam rotation + Script.setTimeout(function() { + rotatingTowardsTarget = false; + }, LOOK_AT_TIME); + + vector = Vec3.subtract(position, center); + targetCamOrientation = orientationOf(vector); + radius = Vec3.length(vector); + azimuth = Math.atan2(vector.z, vector.x); + altitude = Math.asin(vector.y / Vec3.length(vector)); + + isActive = true; } + + } } function mouseReleaseEvent(event) { - if (isActive) { - isActive = false; - } + if (isActive) { + isActive = false; + } } function mouseMoveEvent(event) { - if (isActive && mode != noMode) { - if (mode == radialMode) { - handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == orbitMode) { - handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); - } - if (mode == panningMode) { - handlePanMode(event.x - mouseLastX, event.y - mouseLastY); - } - - mouseLastX = event.x; - mouseLastY = event.y; + if (isActive && mode != noMode && !rotatingTowardsTarget) { + if (mode == radialMode) { + handleRadialMode(event.x - mouseLastX, event.y - mouseLastY); } + if (mode == orbitMode) { + handleOrbitMode(event.x - mouseLastX, event.y - mouseLastY); + } + if (mode == panningMode) { + handlePanMode(event.x - mouseLastX, event.y - mouseLastY); + } + + } + mouseLastX = event.x; + mouseLastY = event.y; } function update() { - handleModes(); + handleModes(); + if (rotatingTowardsTarget) { + rotateTowardsTarget(); + } +} + +function rotateTowardsTarget() { + var newOrientation = Quat.mix(Camera.getOrientation(), targetCamOrientation, .1); + Camera.setOrientation(newOrientation); } function scriptEnding() { - if (mode != noMode) { - restoreCameraState(); - } + if (mode != noMode) { + restoreCameraState(); + } } Controller.keyPressEvent.connect(keyPressEvent); From 35b1a6eee440091a656593df495ffdc2d8f5e235 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 21 May 2015 18:15:05 -0700 Subject: [PATCH 06/19] selectionManager.selections holds ids, not properties --- examples/edit.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 95c4df50c4..7983a49575 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -762,7 +762,7 @@ function mouseClickEvent(event) { selectionManager.addEntity(foundEntity, true); } - print("Model selected: " + foundEntity.id); + print("Model selected: " + foundEntity); selectionDisplay.select(selectedEntityID, event); if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { @@ -1201,7 +1201,7 @@ PropertiesTool = function(opts) { var selections = []; for (var i = 0; i < selectionManager.selections.length; i++) { var entity = {}; - entity.id = selectionManager.selections[i].id; + entity.id = selectionManager.selections[i]; entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); selections.push(entity); @@ -1251,7 +1251,7 @@ PropertiesTool = function(opts) { var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2), var diff = { x: 0, y: dY, z: 0 }; for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; var newPosition = Vec3.sum(properties.position, diff); Entities.editEntity(selectionManager.selections[i], { position: newPosition, @@ -1264,7 +1264,7 @@ PropertiesTool = function(opts) { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; var dY = grid.getOrigin().y - bottomY; var diff = { x: 0, y: dY, z: 0 }; @@ -1280,7 +1280,7 @@ PropertiesTool = function(opts) { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; var naturalDimensions = properties.naturalDimensions; // If any of the natural dimensions are not 0, resize @@ -1302,7 +1302,7 @@ PropertiesTool = function(opts) { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; Entities.editEntity(selectionManager.selections[i], { dimensions: Vec3.multiply(multiplier, properties.dimensions), }); @@ -1314,7 +1314,7 @@ PropertiesTool = function(opts) { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + var properties = selectionManager.savedProperties[selectionManager.selections[i]]; if (properties.type == "Zone") { var centerOfZone = properties.boundingBox.center; var atmosphereCenter = { x: centerOfZone.x, From fe99941de380bf83ec094e92928adf04722677b4 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 21 May 2015 19:35:27 -0700 Subject: [PATCH 07/19] fixed problem with particle entities not showing up on other clients by adding properties to decodeEditEntityPacket and encodeEntityEditPacket methods in EntityItemProperties.cpp --- .../entities/src/EntityItemProperties.cpp | 365 +++++++++--------- libraries/networking/src/PacketHeaders.cpp | 121 +++--- libraries/networking/src/PacketHeaders.h | 22 +- 3 files changed, 261 insertions(+), 247 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index d5f866f045..905fa7d104 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -35,80 +35,80 @@ EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - EntityItemProperties::EntityItemProperties() : - CONSTRUCT_PROPERTY(visible, ENTITY_ITEM_DEFAULT_VISIBLE), - CONSTRUCT_PROPERTY(position, 0), - CONSTRUCT_PROPERTY(dimensions, ENTITY_ITEM_DEFAULT_DIMENSIONS), - CONSTRUCT_PROPERTY(rotation, ENTITY_ITEM_DEFAULT_ROTATION), - CONSTRUCT_PROPERTY(density, ENTITY_ITEM_DEFAULT_DENSITY), - CONSTRUCT_PROPERTY(velocity, ENTITY_ITEM_DEFAULT_VELOCITY), - CONSTRUCT_PROPERTY(gravity, ENTITY_ITEM_DEFAULT_GRAVITY), - CONSTRUCT_PROPERTY(acceleration, ENTITY_ITEM_DEFAULT_ACCELERATION), - CONSTRUCT_PROPERTY(damping, ENTITY_ITEM_DEFAULT_DAMPING), - CONSTRUCT_PROPERTY(restitution, ENTITY_ITEM_DEFAULT_RESTITUTION), - CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION), - CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME), - CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT), - CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL), - CONSTRUCT_PROPERTY(color, ), - CONSTRUCT_PROPERTY(modelURL, ""), - CONSTRUCT_PROPERTY(compoundShapeURL, ""), - CONSTRUCT_PROPERTY(animationURL, ""), - CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS), - CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX), - CONSTRUCT_PROPERTY(animationIsPlaying, ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING), - CONSTRUCT_PROPERTY(registrationPoint, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT), - CONSTRUCT_PROPERTY(angularVelocity, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY), - CONSTRUCT_PROPERTY(angularDamping, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING), - CONSTRUCT_PROPERTY(ignoreForCollisions, ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS), - CONSTRUCT_PROPERTY(collisionsWillMove, ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE), - CONSTRUCT_PROPERTY(isSpotlight, false), - CONSTRUCT_PROPERTY(intensity, 1.0f), - CONSTRUCT_PROPERTY(exponent, 0.0f), - CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF), - CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), - CONSTRUCT_PROPERTY(textures, ""), - CONSTRUCT_PROPERTY(animationSettings, ""), - CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA), - CONSTRUCT_PROPERTY(simulatorID, ENTITY_ITEM_DEFAULT_SIMULATOR_ID), - CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT), - CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT), - CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), - CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR), - CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), - CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), - CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), - CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), - CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), - CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), - CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), - CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), - CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), - CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR), - CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY), - CONSTRUCT_PROPERTY(keyLightAmbientIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY), - CONSTRUCT_PROPERTY(keyLightDirection, ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION), - CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME), - CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT), - CONSTRUCT_PROPERTY(sourceUrl, ""), +CONSTRUCT_PROPERTY(visible, ENTITY_ITEM_DEFAULT_VISIBLE), +CONSTRUCT_PROPERTY(position, 0), +CONSTRUCT_PROPERTY(dimensions, ENTITY_ITEM_DEFAULT_DIMENSIONS), +CONSTRUCT_PROPERTY(rotation, ENTITY_ITEM_DEFAULT_ROTATION), +CONSTRUCT_PROPERTY(density, ENTITY_ITEM_DEFAULT_DENSITY), +CONSTRUCT_PROPERTY(velocity, ENTITY_ITEM_DEFAULT_VELOCITY), +CONSTRUCT_PROPERTY(gravity, ENTITY_ITEM_DEFAULT_GRAVITY), +CONSTRUCT_PROPERTY(acceleration, ENTITY_ITEM_DEFAULT_ACCELERATION), +CONSTRUCT_PROPERTY(damping, ENTITY_ITEM_DEFAULT_DAMPING), +CONSTRUCT_PROPERTY(restitution, ENTITY_ITEM_DEFAULT_RESTITUTION), +CONSTRUCT_PROPERTY(friction, ENTITY_ITEM_DEFAULT_FRICTION), +CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME), +CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT), +CONSTRUCT_PROPERTY(collisionSoundURL, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL), +CONSTRUCT_PROPERTY(color, ), +CONSTRUCT_PROPERTY(modelURL, ""), +CONSTRUCT_PROPERTY(compoundShapeURL, ""), +CONSTRUCT_PROPERTY(animationURL, ""), +CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS), +CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX), +CONSTRUCT_PROPERTY(animationIsPlaying, ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING), +CONSTRUCT_PROPERTY(registrationPoint, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT), +CONSTRUCT_PROPERTY(angularVelocity, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY), +CONSTRUCT_PROPERTY(angularDamping, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING), +CONSTRUCT_PROPERTY(ignoreForCollisions, ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS), +CONSTRUCT_PROPERTY(collisionsWillMove, ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE), +CONSTRUCT_PROPERTY(isSpotlight, false), +CONSTRUCT_PROPERTY(intensity, 1.0f), +CONSTRUCT_PROPERTY(exponent, 0.0f), +CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF), +CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), +CONSTRUCT_PROPERTY(textures, ""), +CONSTRUCT_PROPERTY(animationSettings, ""), +CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA), +CONSTRUCT_PROPERTY(simulatorID, ENTITY_ITEM_DEFAULT_SIMULATOR_ID), +CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT), +CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT), +CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), +CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR), +CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), +CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), +CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), +CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), +CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), +CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), +CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), +CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), +CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), +CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR), +CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY), +CONSTRUCT_PROPERTY(keyLightAmbientIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY), +CONSTRUCT_PROPERTY(keyLightDirection, ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION), +CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME), +CONSTRUCT_PROPERTY(backgroundMode, BACKGROUND_MODE_INHERIT), +CONSTRUCT_PROPERTY(sourceUrl, ""), - _id(UNKNOWN_ENTITY_ID), - _idSet(false), - _lastEdited(0), - _created(UNKNOWN_CREATED_TIME), - _type(EntityTypes::Unknown), +_id(UNKNOWN_ENTITY_ID), +_idSet(false), +_lastEdited(0), +_created(UNKNOWN_CREATED_TIME), +_type(EntityTypes::Unknown), - _glowLevel(0.0f), - _localRenderAlpha(1.0f), +_glowLevel(0.0f), +_localRenderAlpha(1.0f), - _glowLevelChanged(false), - _localRenderAlphaChanged(false), +_glowLevelChanged(false), +_localRenderAlphaChanged(false), - _defaultSettings(true), - _naturalDimensions(1.0f, 1.0f, 1.0f) +_defaultSettings(true), +_naturalDimensions(1.0f, 1.0f, 1.0f) { } -EntityItemProperties::~EntityItemProperties() { +EntityItemProperties::~EntityItemProperties() { } void EntityItemProperties::setSittingPoints(const QVector& sittingPoints) { @@ -118,11 +118,11 @@ void EntityItemProperties::setSittingPoints(const QVector& sitting } } -void EntityItemProperties::setAnimationSettings(const QString& value) { +void EntityItemProperties::setAnimationSettings(const QString& value) { // the animations setting is a JSON string that may contain various animation settings. // if it includes fps, frameIndex, or running, those values will be parsed out and // will over ride the regular animation settings - + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); @@ -130,37 +130,37 @@ void EntityItemProperties::setAnimationSettings(const QString& value) { float fps = settingsMap["fps"].toFloat(); setAnimationFPS(fps); } - + if (settingsMap.contains("frameIndex")) { float frameIndex = settingsMap["frameIndex"].toFloat(); setAnimationFrameIndex(frameIndex); } - + if (settingsMap.contains("running")) { bool running = settingsMap["running"].toBool(); setAnimationIsPlaying(running); } - _animationSettings = value; - _animationSettingsChanged = true; + _animationSettings = value; + _animationSettingsChanged = true; } -QString EntityItemProperties::getAnimationSettings() const { +QString EntityItemProperties::getAnimationSettings() const { // the animations setting is a JSON string that may contain various animation settings. // if it includes fps, frameIndex, or running, those values will be parsed out and // will over ride the regular animation settings QString value = _animationSettings; - + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); QVariant fpsValue(getAnimationFPS()); settingsMap["fps"] = fpsValue; - + QVariant frameIndexValue(getAnimationFrameIndex()); settingsMap["frameIndex"] = frameIndexValue; - + QVariant runningValue(getAnimationIsPlaying()); settingsMap["running"] = runningValue; @@ -180,28 +180,28 @@ void EntityItemProperties::debugDump() const { qCDebug(entities) << " _dimensions=" << getDimensions(); qCDebug(entities) << " _modelURL=" << _modelURL; qCDebug(entities) << " _compoundShapeURL=" << _compoundShapeURL; - + getAtmosphere().debugDump(); getSkybox().debugDump(); - + qCDebug(entities) << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); props.debugDumpBits(); } -void EntityItemProperties::setCreated(quint64 usecTime) { - _created = usecTime; +void EntityItemProperties::setCreated(quint64 usecTime) { + _created = usecTime; if (_lastEdited < _created) { _lastEdited = _created; } } -void EntityItemProperties::setLastEdited(quint64 usecTime) { - _lastEdited = usecTime > _created ? usecTime : _created; +void EntityItemProperties::setLastEdited(quint64 usecTime) { + _lastEdited = usecTime > _created ? usecTime : _created; } const char* shapeTypeNames[] = {"none", "box", "sphere", "ellipsoid", "plane", "compound", "capsule-x", - "capsule-y", "capsule-z", "cylinder-x", "cylinder-y", "cylinder-z"}; + "capsule-y", "capsule-z", "cylinder-x", "cylinder-y", "cylinder-z"}; QHash stringToShapeTypeLookup; @@ -336,22 +336,22 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, keyLightDirection); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_MODE, backgroundMode); CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); - + changedProperties += _stage.getChangedProperties(); changedProperties += _atmosphere.getChangedProperties(); changedProperties += _skybox.getChangedProperties(); - + return changedProperties; } QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults) const { QScriptValue properties = engine->newObject(); EntityItemProperties defaultEntityProperties; - + if (_idSet) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(id, _id.toString()); } - + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(type, EntityTypes::getEntityTypeName(_type)); COPY_PROPERTY_TO_QSCRIPTVALUE(position); COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions); @@ -411,14 +411,14 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); COPY_PROPERTY_TO_QSCRIPTVALUE(name); COPY_PROPERTY_TO_QSCRIPTVALUE(collisionSoundURL); - + COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightColor); COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity); COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity); COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightDirection); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(backgroundMode, getBackgroundModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(sourceUrl); - + // Sitting properties support if (!skipDefaults) { QScriptValue sittingPoints = engine->newObject(); @@ -432,7 +432,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool sittingPoints.setProperty("length", _sittingPoints.size()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable } - + if (!skipDefaults) { AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); @@ -446,7 +446,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool boundingBox.setProperty("dimensions", boundingBoxDimensions); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(boundingBox, boundingBox); // gettable, but not settable } - + QString textureNamesList = _textureNames.join(",\n"); if (!skipDefaults) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable @@ -455,7 +455,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool _stage.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); _atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); _skybox.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties); - + return properties; } @@ -464,7 +464,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { if (typeScriptValue.isValid()) { setType(typeScriptValue.toVariant().toString()); } - + COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition); COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions); COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation); @@ -516,14 +516,14 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID); COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName); COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL); - + COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightColor, xColor, setKeyLightColor); COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightIntensity, float, setKeyLightIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightAmbientIntensity, float, setKeyLightAmbientIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightDirection, glmVec3, setKeyLightDirection); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(backgroundMode, BackgroundMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); - + _stage.copyFromScriptValue(object, _defaultSettings); _atmosphere.copyFromScriptValue(object, _defaultSettings); _skybox.copyFromScriptValue(object, _defaultSettings); @@ -542,8 +542,8 @@ void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemP properties.copyFromScriptValue(object); } -// TODO: Implement support for edit packets that can span an MTU sized buffer. We need to implement a mechanism for the -// encodeEntityEditPacket() method to communicate the the caller which properties couldn't fit in the buffer. Similar +// TODO: Implement support for edit packets that can span an MTU sized buffer. We need to implement a mechanism for the +// encodeEntityEditPacket() method to communicate the the caller which properties couldn't fit in the buffer. Similar // to how we handle this in the Octree streaming case. // // TODO: Right now, all possible properties for all subclasses are handled here. Ideally we'd prefer @@ -561,11 +561,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem unsigned char* bufferOut, int sizeIn, int& sizeOut) { OctreePacketData ourDataPacket(false, sizeIn); // create a packetData object to add out packet details too. OctreePacketData* packetData = &ourDataPacket; // we want a pointer to this so we can use our APPEND_ENTITY_PROPERTY macro - + bool success = true; // assume the best OctreeElement::AppendState appendState = OctreeElement::COMPLETED; // assume the best sizeOut = 0; - + // TODO: We need to review how jurisdictions should be handled for entities. (The old Models and Particles code // didn't do anything special for jurisdictions, so we're keeping that same behavior here.) // @@ -575,35 +575,35 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem glm::vec3 rootPosition(0); float rootScale = 0.5f; unsigned char* octcode = pointToOctalCode(rootPosition.x, rootPosition.y, rootPosition.z, rootScale); - + success = packetData->startSubTree(octcode); delete[] octcode; // assuming we have rome to fit our octalCode, proceed... if (success) { - + // Now add our edit content details... - + // id // encode our ID as a byte count coded byte stream QByteArray encodedID = id.toRfc4122(); // NUM_BYTES_RFC4122_UUID - + // encode our ID as a byte count coded byte stream ByteCountCoded tokenCoder; QByteArray encodedToken; - + // encode our type as a byte count coded byte stream ByteCountCoded typeCoder = (quint32)properties.getType(); QByteArray encodedType = typeCoder; - + quint64 updateDelta = 0; // this is an edit so by definition, it's update is in sync ByteCountCoded updateDeltaCoder = updateDelta; QByteArray encodedUpdateDelta = updateDeltaCoder; - + EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = properties.getChangedProperties(); EntityPropertyFlags propertiesDidntFit = requestedProperties; - + // TODO: we need to handle the multi-pass form of this, similar to how we handle entity data // // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, @@ -611,46 +611,46 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem //if (modelTreeElementExtraEncodeData && modelTreeElementExtraEncodeData->includedItems.contains(getEntityItemID())) { // requestedProperties = modelTreeElementExtraEncodeData->includedItems.value(getEntityItemID()); //} - + LevelDetails entityLevel = packetData->startLevel(); - + // Last Edited quint64 always first, before any other details, which allows us easy access to adjusting this // timestamp for clock skew quint64 lastEdited = properties.getLastEdited(); bool successLastEditedFits = packetData->appendValue(lastEdited); - + bool successIDFits = packetData->appendValue(encodedID); if (successIDFits) { successIDFits = packetData->appendValue(encodedToken); } bool successTypeFits = packetData->appendValue(encodedType); - + // NOTE: We intentionally do not send "created" times in edit messages. This is because: // 1) if the edit is to an existing entity, the created time can not be changed // 2) if the edit is to a new entity, the created time is the last edited time - + // TODO: Should we get rid of this in this in edit packets, since this has to always be 0? bool successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta); - + int propertyFlagsOffset = packetData->getUncompressedByteOffset(); QByteArray encodedPropertyFlags = propertyFlags; int oldPropertyFlagsLength = encodedPropertyFlags.length(); bool successPropertyFlagsFits = packetData->appendValue(encodedPropertyFlags); int propertyCount = 0; - + bool headerFits = successIDFits && successTypeFits && successLastEditedFits - && successLastUpdatedFits && successPropertyFlagsFits; - + && successLastUpdatedFits && successPropertyFlagsFits; + int startOfEntityItemData = packetData->getUncompressedByteOffset(); - + if (headerFits) { bool successPropertyFits; propertyFlags -= PROP_LAST_ITEM; // clear the last item for now, we may or may not set it as the actual item - + // These items would go here once supported.... // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, - + APPEND_ENTITY_PROPERTY(PROP_POSITION, properties.getPosition()); APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, properties.getRotation()); @@ -677,7 +677,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem if (properties.getType() == EntityTypes::Web) { APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl()); } - + if (properties.getType() == EntityTypes::Text) { APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); @@ -696,7 +696,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings()); APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType())); } - + if (properties.getType() == EntityTypes::Light) { APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, properties.getIsSpotlight()); APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); @@ -704,8 +704,13 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_EXPONENT, properties.getExponent()); APPEND_ENTITY_PROPERTY(PROP_CUTOFF, properties.getCutoff()); } - + if (properties.getType() == EntityTypes::ParticleEffect) { + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, properties.getAnimationFPS()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, properties.getAnimationFrameIndex()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, properties.getAnimationIsPlaying()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures()); APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles()); APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); @@ -714,24 +719,24 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); } - + if (properties.getType() == EntityTypes::Zone) { APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, properties.getKeyLightColor()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, properties.getKeyLightIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, properties.getKeyLightAmbientIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, properties.getKeyLightDirection()); - + _staticStage.setProperties(properties); _staticStage.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState ); - + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)properties.getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL()); - + APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)properties.getBackgroundMode()); _staticAtmosphere.setProperties(properties); _staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState ); - + _staticSkybox.setProperties(properties); _staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState ); } @@ -742,41 +747,41 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); - + encodedPropertyFlags = propertyFlags; int newPropertyFlagsLength = encodedPropertyFlags.length(); - packetData->updatePriorBytes(propertyFlagsOffset, - (const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length()); - + packetData->updatePriorBytes(propertyFlagsOffset, + (const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length()); + // if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet. if (newPropertyFlagsLength < oldPropertyFlagsLength) { int oldSize = packetData->getUncompressedSize(); - + const unsigned char* modelItemData = packetData->getUncompressedData(propertyFlagsOffset + oldPropertyFlagsLength); int modelItemDataLength = endOfEntityItemData - startOfEntityItemData; int newEntityItemDataStart = propertyFlagsOffset + newPropertyFlagsLength; packetData->updatePriorBytes(newEntityItemDataStart, modelItemData, modelItemDataLength); - + int newSize = oldSize - (oldPropertyFlagsLength - newPropertyFlagsLength); packetData->setUncompressedSize(newSize); - + } else { assert(newPropertyFlagsLength == oldPropertyFlagsLength); // should not have grown } - + packetData->endLevel(entityLevel); } else { packetData->discardLevel(entityLevel); appendState = OctreeElement::NONE; // if we got here, then we didn't include the item } - + // If any part of the model items didn't fit, then the element is considered partial if (appendState != OctreeElement::COMPLETED) { - + // TODO: handle mechanism for handling partial fitting data! // add this item into our list for the next appendElementData() pass //modelTreeElementExtraEncodeData->includedItems.insert(getEntityItemID(), propertiesDidntFit); - + // for now, if it's not complete, it's not successful success = false; } @@ -801,7 +806,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem return success; } -// TODO: +// TODO: // how to handle lastEdited? // how to handle lastUpdated? // consider handling case where no properties are included... we should just ignore this packet... @@ -820,15 +825,15 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes, EntityItemID& entityID, EntityItemProperties& properties) { bool valid = false; - + const unsigned char* dataAt = data; processedBytes = 0; - + // the first part of the data is an octcode, this is a required element of the edit packet format, but we don't // actually use it, we do need to skip it and read to the actual data we care about. int octets = numberOfThreeBitSectionsInCode(data); int bytesToReadOfOctcode = bytesRequiredForCodeLength(octets); - + // we don't actually do anything with this octcode... dataAt += bytesToReadOfOctcode; processedBytes += bytesToReadOfOctcode; @@ -841,20 +846,20 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int dataAt += sizeof(lastEdited); processedBytes += sizeof(lastEdited); properties.setLastEdited(lastEdited); - + // NOTE: We intentionally do not send "created" times in edit messages. This is because: // 1) if the edit is to an existing entity, the created time can not be changed // 2) if the edit is to a new entity, the created time is the last edited time - + // encoded id QByteArray encodedID((const char*)dataAt, NUM_BYTES_RFC4122_UUID); // maximum possible size QUuid editID = QUuid::fromRfc4122(encodedID); dataAt += encodedID.size(); processedBytes += encodedID.size(); - + entityID = editID; valid = true; - + // Entity Type... QByteArray encodedType((const char*)dataAt, (bytesToRead - processedBytes)); ByteCountCoded typeCoder = encodedType; @@ -863,18 +868,18 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int encodedType = typeCoder; // determine true bytesToRead dataAt += encodedType.size(); processedBytes += encodedType.size(); - + // Update Delta - when was this item updated relative to last edit... this really should be 0 // TODO: Should we get rid of this in this in edit packets, since this has to always be 0? // TODO: do properties need to handle lastupdated??? - + // last updated is stored as ByteCountCoded delta from lastEdited QByteArray encodedUpdateDelta((const char*)dataAt, (bytesToRead - processedBytes)); ByteCountCoded updateDeltaCoder = encodedUpdateDelta; encodedUpdateDelta = updateDeltaCoder; // determine true bytesToRead dataAt += encodedUpdateDelta.size(); processedBytes += encodedUpdateDelta.size(); - + // TODO: Do we need this lastUpdated?? We don't seem to use it. //quint64 updateDelta = updateDeltaCoder; //quint64 lastUpdated = lastEdited + updateDelta; // don't adjust for clock skew since we already did that for lastEdited @@ -884,7 +889,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int EntityPropertyFlags propertyFlags = encodedPropertyFlags; dataAt += propertyFlags.getEncodedLength(); processedBytes += propertyFlags.getEncodedLength(); - + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POSITION, glm::vec3, setPosition); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, glm::vec3, setDimensions); // NOTE: PROP_RADIUS obsolete READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ROTATION, glm::quat, setRotation); @@ -907,11 +912,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SIMULATOR_ID, QUuid, setSimulatorID); - + if (properties.getType() == EntityTypes::Web) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); } - + if (properties.getType() == EntityTypes::Text) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); @@ -938,8 +943,14 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff); } - + if (properties.getType() == EntityTypes::ParticleEffect) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); @@ -948,15 +959,15 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } - + if (properties.getType() == EntityTypes::Zone) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_COLOR, xColor, setKeyLightColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection); - + properties.getStage().decodeFromEditPacket(propertyFlags, dataAt , processedBytes); - + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode); @@ -967,20 +978,20 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL); - + return valid; } // NOTE: This version will only encode the portion of the edit message immediately following the -// header it does not include the send times and sequence number because that is handled by the +// header it does not include the send times and sequence number because that is handled by the // edit packet sender... -bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityItemID, +bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityItemID, unsigned char* outputBuffer, size_t maxLength, size_t& outputLength) { - + unsigned char* copyAt = outputBuffer; uint16_t numberOfIds = 1; // only one entity ID in this message - + if (maxLength < sizeof(numberOfIds) + NUM_BYTES_RFC4122_UUID) { qCDebug(entities) << "ERROR - encodeEraseEntityMessage() called with buffer that is too small!"; outputLength = 0; @@ -989,14 +1000,14 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt memcpy(copyAt, &numberOfIds, sizeof(numberOfIds)); copyAt += sizeof(numberOfIds); outputLength = sizeof(numberOfIds); - + QUuid entityID = entityItemID; QByteArray encodedEntityID = entityID.toRfc4122(); - + memcpy(copyAt, encodedEntityID.constData(), NUM_BYTES_RFC4122_UUID); copyAt += NUM_BYTES_RFC4122_UUID; outputLength += NUM_BYTES_RFC4122_UUID; - + return true; } @@ -1034,7 +1045,7 @@ void EntityItemProperties::markAllChanged() { _isSpotlightChanged = true; _ignoreForCollisionsChanged = true; _collisionsWillMoveChanged = true; - + _intensityChanged = true; _exponentChanged = true; _cutoffChanged = true; @@ -1046,7 +1057,7 @@ void EntityItemProperties::markAllChanged() { _textColorChanged = true; _backgroundColorChanged = true; _shapeTypeChanged = true; - + _maxParticlesChanged = true; _lifespanChanged = true; _emitRateChanged = true; @@ -1056,7 +1067,7 @@ void EntityItemProperties::markAllChanged() { _particleRadiusChanged = true; _marketplaceIDChanged = true; - + _keyLightColorChanged = true; _keyLightIntensityChanged = true; _keyLightAmbientIntensityChanged = true; @@ -1066,39 +1077,39 @@ void EntityItemProperties::markAllChanged() { _stage.markAllChanged(); _atmosphere.markAllChanged(); _skybox.markAllChanged(); - + _sourceUrlChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. /// This accounts for the registration point (upon which rotation occurs around). -/// -AACube EntityItemProperties::getMaximumAACube() const { +/// +AACube EntityItemProperties::getMaximumAACube() const { // * we know that the position is the center of rotation glm::vec3 centerOfRotation = _position; // also where _registration point is - + // * we know that the registration point is the center of rotation // * we can calculate the length of the furthest extent from the registration point // as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint) glm::vec3 registrationPoint = (_dimensions * _registrationPoint); glm::vec3 registrationRemainder = (_dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint)); glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder); - + // * we know that if you rotate in any direction you would create a sphere // that has a radius of the length of furthest extent from registration point float radius = glm::length(furthestExtentFromRegistration); - + // * we know that the minimum bounding cube of this maximum possible sphere is // (center - radius) to (center + radius) glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius); float diameter = radius * 2.0f; - + return AACube(minimumCorner, diameter); } // The minimum bounding box for the entity. -AABox EntityItemProperties::getAABox() const { - +AABox EntityItemProperties::getAABox() const { + // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 6a5b703a29..c5030fb1e7 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -87,49 +87,50 @@ PacketVersion versionForPacketType(PacketType packetType) { QString nameForPacketType(PacketType packetType) { switch (packetType) { - PACKET_TYPE_NAME_LOOKUP(PacketTypeUnknown); - PACKET_TYPE_NAME_LOOKUP(PacketTypeStunResponse); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainList); - PACKET_TYPE_NAME_LOOKUP(PacketTypePing); - PACKET_TYPE_NAME_LOOKUP(PacketTypePingReply); - PACKET_TYPE_NAME_LOOKUP(PacketTypeKillAvatar); - PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeInjectAudio); - PACKET_TYPE_NAME_LOOKUP(PacketTypeMixedAudio); - PACKET_TYPE_NAME_LOOKUP(PacketTypeMicrophoneAudioNoEcho); - PACKET_TYPE_NAME_LOOKUP(PacketTypeMicrophoneAudioWithEcho); - PACKET_TYPE_NAME_LOOKUP(PacketTypeBulkAvatarData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeSilentAudioFrame); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEnvironmentData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainListRequest); - PACKET_TYPE_NAME_LOOKUP(PacketTypeRequestAssignment); - PACKET_TYPE_NAME_LOOKUP(PacketTypeCreateAssignment); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainConnectionDenied); - PACKET_TYPE_NAME_LOOKUP(PacketTypeMuteEnvironment); - PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioStreamStats); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDataServerConfirm); - PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeStats); - PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdiction); - PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdictionRequest); - PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarIdentity); - PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarBillboard); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainConnectRequest); - PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainServerRequireDTLS); - PACKET_TYPE_NAME_LOOKUP(PacketTypeNodeJsonStats); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityQuery); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityData); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); - PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); - PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); - PACKET_TYPE_NAME_LOOKUP(PacketTypeIceServerHeartbeat); - PACKET_TYPE_NAME_LOOKUP(PacketTypeIceServerHeartbeatResponse); - PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPing); - PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPingReply); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAdd); - PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEdit); + PACKET_TYPE_NAME_LOOKUP(PacketTypeUnknown); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStunResponse); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainList); + PACKET_TYPE_NAME_LOOKUP(PacketTypePing); + PACKET_TYPE_NAME_LOOKUP(PacketTypePingReply); + PACKET_TYPE_NAME_LOOKUP(PacketTypeKillAvatar); + PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarData); + PACKET_TYPE_NAME_LOOKUP(PacketTypeInjectAudio); + PACKET_TYPE_NAME_LOOKUP(PacketTypeMixedAudio); + PACKET_TYPE_NAME_LOOKUP(PacketTypeMicrophoneAudioNoEcho); + PACKET_TYPE_NAME_LOOKUP(PacketTypeMicrophoneAudioWithEcho); + PACKET_TYPE_NAME_LOOKUP(PacketTypeBulkAvatarData); + PACKET_TYPE_NAME_LOOKUP(PacketTypeSilentAudioFrame); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEnvironmentData); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainListRequest); + PACKET_TYPE_NAME_LOOKUP(PacketTypeRequestAssignment); + PACKET_TYPE_NAME_LOOKUP(PacketTypeCreateAssignment); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainConnectionDenied); + PACKET_TYPE_NAME_LOOKUP(PacketTypeMuteEnvironment); + PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioStreamStats); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDataServerConfirm); + PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeStats); + PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdiction); + PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdictionRequest); + PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarIdentity); + PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarBillboard); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainConnectRequest); + PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainServerRequireDTLS); + PACKET_TYPE_NAME_LOOKUP(PacketTypeNodeJsonStats); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityQuery); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityData); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); + PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); + PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); + PACKET_TYPE_NAME_LOOKUP(PacketTypeIceServerHeartbeat); + PACKET_TYPE_NAME_LOOKUP(PacketTypeIceServerHeartbeatResponse); + PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPing); + PACKET_TYPE_NAME_LOOKUP(PacketTypeUnverifiedPingReply); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAdd); + PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEdit); + PACKET_TYPE_NAME_LOOKUP(PacketTypeParticleEntitiesFix); default: return QString("Type: ") + QString::number((int)packetType); } @@ -167,14 +168,14 @@ int populatePacketHeaderWithUUID(char* packet, PacketType packetType, const QUui memset(position, 0, NUM_BYTES_MD5_HASH); position += NUM_BYTES_MD5_HASH; } - + if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { - // Pack zeros for the number of bytes that the sequence number requires. - // The LimitedNodeList will handle packing in the sequence number when sending out the packet. - memset(position, 0, sizeof(PacketSequenceNumber)); - position += sizeof(PacketSequenceNumber); + // Pack zeros for the number of bytes that the sequence number requires. + // The LimitedNodeList will handle packing in the sequence number when sending out the packet. + memset(position, 0, sizeof(PacketSequenceNumber)); + position += sizeof(PacketSequenceNumber); } - + // return the number of bytes written for pointer pushing return position - packet; } @@ -194,7 +195,7 @@ int numBytesForArithmeticCodedPacketType(PacketType packetType) { } int numBytesForPacketHeaderGivenPacketType(PacketType packetType) { - return numBytesForArithmeticCodedPacketType(packetType) + return numBytesForArithmeticCodedPacketType(packetType) + numHashBytesForType(packetType) + numSequenceNumberBytesForType(packetType) + NUM_STATIC_HEADER_BYTES; @@ -214,7 +215,7 @@ QUuid uuidFromPacketHeader(const QByteArray& packet) { } int hashOffsetForPacketType(PacketType packetType) { - return numBytesForArithmeticCodedPacketType(packetType) + NUM_STATIC_HEADER_BYTES; + return numBytesForArithmeticCodedPacketType(packetType) + NUM_STATIC_HEADER_BYTES; } int sequenceNumberOffsetForPacketType(PacketType packetType) { @@ -234,13 +235,13 @@ PacketSequenceNumber sequenceNumberFromHeader(const QByteArray& packet, PacketTy if (packetType == PacketTypeUnknown) { packetType = packetTypeForPacket(packet); } - + PacketSequenceNumber result = DEFAULT_SEQUENCE_NUMBER; if (SEQUENCE_NUMBERED_PACKETS.contains(packetType)) { memcpy(&result, packet.data() + sequenceNumberOffsetForPacketType(packetType), sizeof(PacketSequenceNumber)); - } - + } + return result; } @@ -249,7 +250,7 @@ void replaceHashInPacket(QByteArray& packet, const QUuid& connectionUUID, Packet packetType = packetTypeForPacket(packet); } - packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH, + packet.replace(hashOffsetForPacketType(packetType), NUM_BYTES_MD5_HASH, hashForPacketAndConnectionUUID(packet, connectionUUID)); } @@ -257,17 +258,17 @@ void replaceSequenceNumberInPacket(QByteArray& packet, PacketSequenceNumber sequ if (packetType == PacketTypeUnknown) { packetType = packetTypeForPacket(packet); } - - packet.replace(sequenceNumberOffsetForPacketType(packetType), + + packet.replace(sequenceNumberOffsetForPacketType(packetType), sizeof(PacketSequenceNumber), reinterpret_cast(&sequenceNumber), sizeof(PacketSequenceNumber)); -} +} -void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber, +void replaceHashAndSequenceNumberInPacket(QByteArray& packet, const QUuid& connectionUUID, PacketSequenceNumber sequenceNumber, PacketType packetType) { if (packetType == PacketTypeUnknown) { packetType = packetTypeForPacket(packet); } - + replaceHashInPacket(packet, connectionUUID, packetType); replaceSequenceNumberInPacket(packet, sequenceNumber, packetType); } diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index d64986c1a0..8b952e6eb3 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -79,7 +79,8 @@ enum PacketType { PacketTypeIceServerHeartbeat, // 50 PacketTypeIceServerHeartbeatResponse, PacketTypeUnverifiedPing, - PacketTypeUnverifiedPingReply + PacketTypeUnverifiedPingReply, + PacketTypeParticleEntitiesFix }; typedef char PacketVersion; @@ -90,17 +91,17 @@ const PacketSequenceNumber DEFAULT_SEQUENCE_NUMBER = 0; typedef std::map PacketTypeSequenceMap; const QSet NON_VERIFIED_PACKETS = QSet() - << PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest - << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied - << PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse - << PacketTypeNodeJsonStats << PacketTypeEntityQuery - << PacketTypeOctreeDataNack << PacketTypeEntityEditNack - << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode - << PacketTypeDomainServerPathQuery << PacketTypeDomainServerPathResponse; +<< PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest +<< PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeDomainConnectionDenied +<< PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse +<< PacketTypeNodeJsonStats << PacketTypeEntityQuery +<< PacketTypeOctreeDataNack << PacketTypeEntityEditNack +<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse +<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode +<< PacketTypeDomainServerPathQuery << PacketTypeDomainServerPathResponse; const QSet SEQUENCE_NUMBERED_PACKETS = QSet() - << PacketTypeAvatarData; +<< PacketTypeAvatarData; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; @@ -179,5 +180,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_LINE_TYPE = 24; const PacketVersion VERSION_ENTITIES_HAVE_COLLISION_SOUND_URL = 25; const PacketVersion VERSION_ENTITIES_HAVE_FRICTION = 26; const PacketVersion VERSION_NO_ENTITY_ID_SWAP = 27; +const PacketVersion VERSION_ENTITIES_PARTICLE_FIX = 28; #endif // hifi_PacketHeaders_h From a0c3c974a9315f0817a14f5d373eddc03b51f0e2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 21 May 2015 19:44:38 -0700 Subject: [PATCH 08/19] Throttle DDE face acquisition attempts in order to reduce CPU usage --- interface/src/devices/DdeFaceTracker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index f37007894b..fba37736e3 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -38,6 +38,7 @@ static const QString DDE_PROGRAM_PATH = "/dde.app/Contents/MacOS/dde"; static const QStringList DDE_ARGUMENTS = QStringList() << "--udp=" + DDE_SERVER_ADDR.toString() + ":" + QString::number(DDE_SERVER_PORT) << "--receiver=" + QString::number(DDE_CONTROL_PORT) + << "--facedet_interval=500" // ms << "--headless"; static const int NUM_EXPRESSIONS = 46; From c6ce5e7680a629190aa3a2a4e4782e868f62bf07 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 22 May 2015 18:54:40 +0200 Subject: [PATCH 09/19] PerformanceTimer deactivated when not in use --- interface/src/ui/ApplicationOverlay.cpp | 8 ++++ interface/src/ui/Stats.cpp | 9 +++-- interface/src/ui/Stats.h | 2 + libraries/shared/src/PerfStat.cpp | 49 ++++++++++++++++++------- libraries/shared/src/PerfStat.h | 6 ++- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index e3f9216c13..c65de2afb0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -979,6 +979,14 @@ void ApplicationOverlay::renderStatsAndLogs() { glLineWidth(1.0f); glPointSize(1.0f); + // Determine whether to compute timing details + bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && + Menu::getInstance()->isOptionChecked(MenuOption::Stats) && + Stats::getInstance()->isExpanded(); + if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) { + PerformanceTimer::setActive(shouldDisplayTimingDetail); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 161eb06f5f..c49208c835 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -224,9 +224,10 @@ void Stats::display( lines = 5; int columnOneWidth = _generalStatsWidth; - PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up - - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { + bool performanceTimerIsActive = PerformanceTimer::isActive(); + bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); + if (displayPerf && performanceTimerIsActive) { + PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide... // we will also include room for 1 line per timing record and a header of 4 lines @@ -276,7 +277,7 @@ void Stats::display( // TODO: the display of these timing details should all be moved to JavaScript - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { + if (displayPerf && performanceTimerIsActive) { bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); // Timing details... verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 406496d858..00c1650b71 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -27,6 +27,8 @@ public: static void drawBackground(unsigned int rgba, int x, int y, int width, int height); void toggleExpanded(); + bool isExpanded() { return _expanded; } + void checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset); void resetWidth(int width, int horizontalOffset); void display(const float* color, int horizontalOffset, float fps, int inPacketsPerSecond, int outPacketsPerSecond, diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 286d257d1f..22cf000c24 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -79,29 +79,50 @@ void PerformanceTimerRecord::tallyResult(const quint64& now) { // PerformanceTimer // ---------------------------------------------------------------------------- +std::atomic PerformanceTimer::_isActive(false); QHash PerformanceTimer::_fullNames; QMap PerformanceTimer::_records; -PerformanceTimer::PerformanceTimer(const QString& name) : - _start(0), - _name(name) -{ - QString& fullName = _fullNames[QThread::currentThread()]; - fullName.append("/"); - fullName.append(_name); - _start = usecTimestampNow(); +PerformanceTimer::PerformanceTimer(const QString& name) { + if (_isActive) { + _name = name; + QString& fullName = _fullNames[QThread::currentThread()]; + fullName.append("/"); + fullName.append(_name); + _start = usecTimestampNow(); + } } PerformanceTimer::~PerformanceTimer() { - quint64 elapsedusec = (usecTimestampNow() - _start); - QString& fullName = _fullNames[QThread::currentThread()]; - PerformanceTimerRecord& namedRecord = _records[fullName]; - namedRecord.accumulateResult(elapsedusec); - fullName.resize(fullName.size() - (_name.size() + 1)); + if (_isActive && _start != 0) { + quint64 elapsedusec = (usecTimestampNow() - _start); + QString& fullName = _fullNames[QThread::currentThread()]; + PerformanceTimerRecord& namedRecord = _records[fullName]; + namedRecord.accumulateResult(elapsedusec); + fullName.resize(fullName.size() - (_name.size() + 1)); + } } -// static +// static +bool PerformanceTimer::PerformanceTimer::isActive() { + return _isActive; +} + +// static +void PerformanceTimer::setActive(bool active) { + if (active != _isActive) { + _isActive.store(active); + if (!active) { + _fullNames.clear(); + _records.clear(); + } + + qDebug() << "PerformanceTimer has been turned" << ((active) ? "on" : "off"); + } +} + +// static void PerformanceTimer::tallyAllTimerRecords() { QMap::iterator recordsItr = _records.begin(); QMap::const_iterator recordsEnd = _records.end(); diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 81731abfa9..2d5a54db38 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -76,14 +76,18 @@ public: PerformanceTimer(const QString& name); ~PerformanceTimer(); + static bool isActive(); + static void setActive(bool active); + static const PerformanceTimerRecord& getTimerRecord(const QString& name) { return _records[name]; }; static const QMap& getAllTimerRecords() { return _records; }; static void tallyAllTimerRecords(); static void dumpAllTimerRecords(); private: - quint64 _start; + quint64 _start = 0; QString _name; + static std::atomic _isActive; static QHash _fullNames; static QMap _records; }; From d40d9cca6937561292004641be017958c430d352 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 22 May 2015 10:02:28 -0700 Subject: [PATCH 10/19] deleted look.js (no longer needed) and removed from default scripts --- examples/defaultScripts.js | 1 - examples/look.js | 183 ------------------------------------- 2 files changed, 184 deletions(-) delete mode 100644 examples/look.js diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index ff22f68cb5..8f32b80bba 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -15,7 +15,6 @@ Script.load("controllers/hydra/hydraMove.js"); Script.load("inspect.js"); Script.load("lobby.js"); Script.load("notifications.js"); -Script.load("look.js"); Script.load("users.js"); Script.load("grab.js"); Script.load("pointer.js"); diff --git a/examples/look.js b/examples/look.js deleted file mode 100644 index 7adcd054c2..0000000000 --- a/examples/look.js +++ /dev/null @@ -1,183 +0,0 @@ -// -// look.js -// examples -// -// Copyright 2015 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Controller class -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var wantDebugging = false; - - -// Configuration -var TOUCH_YAW_SCALE = -0.25; -var TOUCH_PITCH_SCALE = -12.5; -var FIXED_TOUCH_TIMESTEP = 0.016; - -var MOUSE_YAW_SCALE = -0.25; -var MOUSE_PITCH_SCALE = -12.5; -var FIXED_MOUSE_TIMESTEP = 0.016; - -// Mouse Data -var alwaysLook = false; // if you want the mouse look to happen only when you click, change this to false -var isMouseDown = false; -var lastTouchX = 0; -var lastTouchY = 0; -var yawFromTouch = 0; -var pitchFromTouch = 0; - -// Touch Data -var TIME_BEFORE_GENERATED_END_TOUCH_EVENT = 50; // ms -var startedTouching = false; -var lastTouchEvent = 0; -var lastMouseX = 0; -var lastMouseY = 0; -var yawFromMouse = 0; -var pitchFromMouse = 0; - - -// Mouse Events -function mousePressEvent(event) { - if (wantDebugging) { - print("mousePressEvent event.x,y=" + event.x + ", " + event.y); - } - if (event.isRightButton) { - isMouseDown = true; - lastMouseX = event.x; - lastMouseY = event.y; - } -} - -function mouseReleaseEvent(event) { - if (wantDebugging) { - print("mouseReleaseEvent event.x,y=" + event.x + ", " + event.y); - } - isMouseDown = false; -} - -function mouseMoveEvent(event) { - if (wantDebugging) { - print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y); - } - - if (alwaysLook || isMouseDown) { - yawFromMouse += ((event.x - lastMouseX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP); - pitchFromMouse += ((event.y - lastMouseY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP); - lastMouseX = event.x; - lastMouseY = event.y; - } -} - -// Touch Events -function touchBeginEvent(event) { - if (wantDebugging) { - print("touchBeginEvent event.x,y=" + event.x + ", " + event.y); - } - lastTouchX = event.x; - lastTouchY = event.y; - yawFromTouch = 0; - pitchFromTouch = 0; - startedTouching = true; - var d = new Date(); - lastTouchEvent = d.getTime(); -} - -function touchEndEvent(event) { - if (wantDebugging) { - if (event) { - print("touchEndEvent event.x,y=" + event.x + ", " + event.y); - } else { - print("touchEndEvent generated"); - } - } - startedTouching = false; -} - -function touchUpdateEvent(event) { - // print("TOUCH UPDATE"); - if (wantDebugging) { - print("touchUpdateEvent event.x,y=" + event.x + ", " + event.y); - } - - if (!startedTouching) { - // handle Qt 5.4.x bug where we get touch update without a touch begin event - touchBeginEvent(event); - return; - } - - yawFromTouch += ((event.x - lastTouchX) * TOUCH_YAW_SCALE * FIXED_TOUCH_TIMESTEP); - pitchFromTouch += ((event.y - lastTouchY) * TOUCH_PITCH_SCALE * FIXED_TOUCH_TIMESTEP); - lastTouchX = event.x; - lastTouchY = event.y; - var d = new Date(); - lastTouchEvent = d.getTime(); -} - - -function update(deltaTime) { - if (wantDebugging) { - print("update()..."); - } - - if (startedTouching) { - var d = new Date(); - var sinceLastTouch = d.getTime() - lastTouchEvent; - if (sinceLastTouch > TIME_BEFORE_GENERATED_END_TOUCH_EVENT) { - touchEndEvent(); - } - } - - if (yawFromTouch != 0 || yawFromMouse != 0) { - var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollRadians(0, yawFromTouch + yawFromMouse, 0)); - - if (wantDebugging) { - print("changing orientation" - + " [old]MyAvatar.orientation="+MyAvatar.orientation.x + "," + MyAvatar.orientation.y + "," - + MyAvatar.orientation.z + "," + MyAvatar.orientation.w - + " newOrientation="+newOrientation.x + "," + newOrientation.y + "," + newOrientation.z + "," + newOrientation.w); - } - - MyAvatar.orientation = newOrientation; - yawFromTouch = 0; - yawFromMouse = 0; - } - - if (pitchFromTouch != 0 || pitchFromMouse != 0) { - var newPitch = MyAvatar.headPitch + pitchFromTouch + pitchFromMouse; - - if (wantDebugging) { - print("changing pitch [old]MyAvatar.headPitch="+MyAvatar.headPitch+ " newPitch="+newPitch); - } - - MyAvatar.headPitch = newPitch; - pitchFromTouch = 0; - pitchFromMouse = 0; - } -} - - -// Map the mouse events to our functions -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -// Map the mouse events to our functions -Controller.touchBeginEvent.connect(touchBeginEvent); -Controller.touchUpdateEvent.connect(touchUpdateEvent); -Controller.touchEndEvent.connect(touchEndEvent); - -// disable the standard application for mouse events -Controller.captureTouchEvents(); - -function scriptEnding() { - // re-enabled the standard application for mouse events - Controller.releaseTouchEvents(); -} - -// would be nice to change to update -Script.update.connect(update); -Script.scriptEnding.connect(scriptEnding); From e2769266089ef2270e83e7974ffcccdf74b7917b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Brisset?= Date: Fri, 22 May 2015 18:23:42 +0100 Subject: [PATCH 11/19] Add include/remove duplicate type --- libraries/shared/src/PerfStat.cpp | 2 +- libraries/shared/src/PerfStat.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 22cf000c24..615330e13f 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -105,7 +105,7 @@ PerformanceTimer::~PerformanceTimer() { } // static -bool PerformanceTimer::PerformanceTimer::isActive() { +bool PerformanceTimer::isActive() { return _isActive; } diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 2d5a54db38..523bee0808 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -19,6 +19,7 @@ #include "SharedUtil.h" #include "SimpleMovingAverage.h" +#include #include #include #include From a01830f8f858ec6398b79bd865acce01975e5c6e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 22 May 2015 12:32:02 -0700 Subject: [PATCH 12/19] Fix some double to float conversion warnings in Windows builds --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- .../entities-renderer/src/RenderableWebEntityItem.cpp | 4 ++-- tools/vhacd-util/src/VHACDUtilApp.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 7bc253d00a..c47c24f20a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1175,7 +1175,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons return; } // Don't respond to small continuous contacts. - const float COLLISION_MINUMUM_PENETRATION = 0.005; + const float COLLISION_MINUMUM_PENETRATION = 0.005f; if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) { return; } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index f416fff744..1f71e10d4e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -25,8 +25,8 @@ #include "EntityTreeRenderer.h" -const float DPI = 30.47; -const float METERS_TO_INCHES = 39.3701; +const float DPI = 30.47f; +const float METERS_TO_INCHES = 39.3701f; EntityItem* RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new RenderableWebEntityItem(entityID, properties); diff --git a/tools/vhacd-util/src/VHACDUtilApp.cpp b/tools/vhacd-util/src/VHACDUtilApp.cpp index 46e1898979..ed4dab020f 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.cpp +++ b/tools/vhacd-util/src/VHACDUtilApp.cpp @@ -255,27 +255,27 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : vHacdDepth = parser.value(vHacdDepthOption).toInt(); } - float vHacdAlpha = 0.05; + float vHacdAlpha = 0.05f; if (parser.isSet(vHacdAlphaOption)) { vHacdAlpha = parser.value(vHacdAlphaOption).toFloat(); } - float vHacdBeta = 0.05; + float vHacdBeta = 0.05f; if (parser.isSet(vHacdBetaOption)) { vHacdBeta = parser.value(vHacdBetaOption).toFloat(); } - float vHacdGamma = 0.00125; + float vHacdGamma = 0.00125f; if (parser.isSet(vHacdGammaOption)) { vHacdGamma = parser.value(vHacdGammaOption).toFloat(); } - float vHacdDelta = 0.05; + float vHacdDelta = 0.05f; if (parser.isSet(vHacdDeltaOption)) { vHacdDelta = parser.value(vHacdDeltaOption).toFloat(); } - float vHacdConcavity = 0.0025; + float vHacdConcavity = 0.0025f; if (parser.isSet(vHacdConcavityOption)) { vHacdConcavity = parser.value(vHacdConcavityOption).toFloat(); } From 945a84d24fbbada93f656233749d83b4611dad17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 22 May 2015 15:01:43 -0700 Subject: [PATCH 13/19] adjust logic used by the entity-server to decide if the contents of an octree-element have already been sent to a particular interface with a particular frustum --- assignment-client/src/octree/OctreeQueryNode.cpp | 3 +-- assignment-client/src/octree/OctreeQueryNode.h | 6 +++++- assignment-client/src/octree/OctreeSendThread.cpp | 14 ++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 35f8fb9973..56d5e041a9 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -325,8 +325,7 @@ void OctreeQueryNode::updateLastKnownViewFrustum() { } // save that we know the view has been sent. - quint64 now = usecTimestampNow(); - setLastTimeBagEmpty(now); // is this what we want? poor names + setLastTimeBagEmpty(); } diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index ea0f3240aa..ff59fb7685 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -77,7 +77,7 @@ public: bool moveShouldDump() const; quint64 getLastTimeBagEmpty() const { return _lastTimeBagEmpty; } - void setLastTimeBagEmpty(quint64 lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; } + void setLastTimeBagEmpty() { _lastTimeBagEmpty = _sceneSendStartTime; } bool getCurrentPacketIsColor() const { return _currentPacketIsColor; } bool getCurrentPacketIsCompressed() const { return _currentPacketIsCompressed; } @@ -98,6 +98,8 @@ public: void setLastRootTimestamp(quint64 timestamp) { _lastRootTimestamp = timestamp; } unsigned int getlastOctreePacketLength() const { return _lastOctreePacketLength; } int getDuplicatePacketCount() const { return _duplicatePacketCount; } + + void sceneStart(quint64 sceneSendStartTime) { _sceneSendStartTime = sceneSendStartTime; } void nodeKilled(); void forceNodeShutdown(); @@ -158,6 +160,8 @@ private: SentPacketHistory _sentPacketHistory; QQueue _nackedSequenceNumbers; + + quint64 _sceneSendStartTime = 0; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 2014c56476..f85d09b169 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -343,8 +343,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (!viewFrustumChanged && !nodeData->getWantDelta()) { // only set our last sent time if we weren't resetting due to frustum change - quint64 now = usecTimestampNow(); - nodeData->setLastTimeBagEmpty(now); + nodeData->setLastTimeBagEmpty(); } // track completed scenes and send out the stats packet accordingly @@ -368,9 +367,11 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // TODO: add these to stats page //::startSceneSleepTime = _usleepTime; - + + nodeData->sceneStart(usecTimestampNow() - CHANGE_FUDGE); // start tracking our stats - nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); + nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, + _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); // This is the start of "resending" the scene. bool dontRestartSceneOnMove = false; // this is experimental @@ -561,6 +562,11 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } + if (somethingToSend) { + qDebug() << "Hit PPS Limit"; + } + + // Here's where we can/should allow the server to send other data... // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets From 53fe41ef4da605c5f7b8fb3138e954e3a64fcf5a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 22 May 2015 15:11:56 -0700 Subject: [PATCH 14/19] improve a debug print --- assignment-client/src/octree/OctreeSendThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index f85d09b169..972debb21f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -563,7 +563,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (somethingToSend) { - qDebug() << "Hit PPS Limit"; + qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval + << " maxPacketsPerInterval = " << maxPacketsPerInterval; } From 32cc0eacfc0838861375539a5ca8549c2879feb6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 22 May 2015 15:21:26 -0700 Subject: [PATCH 15/19] improve a debug print --- assignment-client/src/octree/OctreeSendThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 972debb21f..d664fb5c8f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -564,7 +564,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (somethingToSend) { qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval - << " maxPacketsPerInterval = " << maxPacketsPerInterval; + << " maxPacketsPerInterval = " << maxPacketsPerInterval + << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; } From 71c0aa4913371350628c34c9f6d6fc235a2aa7df Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 22 May 2015 15:33:38 -0700 Subject: [PATCH 16/19] renamed ajt-test to particles.js since ajt-test doesn't tell us anything about what the script does --- examples/{ajt-test.js => particles.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{ajt-test.js => particles.js} (100%) diff --git a/examples/ajt-test.js b/examples/particles.js similarity index 100% rename from examples/ajt-test.js rename to examples/particles.js From 9a2948978463c8ef45bf2ea567df47e3c7260d86 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sat, 23 May 2015 17:57:25 +0100 Subject: [PATCH 17/19] expose particle properties for editing I have made these changes to aid with experimenting with particles when running the edit scripts locally. --- examples/html/entityProperties.html | 91 ++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a2ff71d010..ece2da7760 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -287,6 +287,18 @@ allSections.push(elWebSections); var elWebSourceURL = document.getElementById("property-web-source-url"); + var elParticleSections = document.querySelectorAll(".particle-section"); + allSections.push(elParticleSections); + var elParticleMaxParticles = document.getElementById("property-particle-maxparticles"); + var elParticleLifeSpan = document.getElementById("property-particle-lifespan"); + var elParticleEmitRate = document.getElementById("property-particle-emit-rate"); + var elParticleEmitDirectionX = document.getElementById("property-particle-emit-direction-x"); + var elParticleEmitDirectionY = document.getElementById("property-particle-emit-direction-y"); + var elParticleEmitDirectionZ = document.getElementById("property-particle-emit-direction-z"); + var elParticleEmitStrength = document.getElementById("property-particle-emit-strength"); + var elParticleLocalGravity = document.getElementById("property-particle-localgravity"); + var elParticleRadius = document.getElementById("property-particle-radius"); + var elTextSections = document.querySelectorAll(".text-section"); allSections.push(elTextSections); var elTextText = document.getElementById("property-text-text"); @@ -455,7 +467,7 @@ } } - if (properties.type == "Box" || properties.type == "Sphere") { + if (properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { elColorSection.style.display = 'block'; elColorRed.value = properties.color.red; elColorGreen.value = properties.color.green; @@ -465,7 +477,7 @@ elColorSection.style.display = 'none'; } - if (properties.type == "Model") { + if (properties.type == "Model" || properties.type == "ParticleEffect") { for (var i = 0; i < elModelSections.length; i++) { elModelSections[i].style.display = 'block'; } @@ -480,6 +492,21 @@ elModelAnimationSettings.value = properties.animationSettings; elModelTextures.value = properties.textures; elModelOriginalTextures.value = properties.originalTextures; + if (properties.type == "ParticleEffect") { + for (var i = 0; i < elParticleSections.length; i++) { + elParticleSections[i].style.display = 'block'; + } + + elParticleMaxParticles.value = properties.maxParticles; + elParticleLifeSpan.value = properties.lifespan.toFixed(2); + elParticleEmitRate.value = properties.emitRate.toFixed(1); + elParticleEmitDirectionX.value = properties.emitDirection.x.toFixed(2); + elParticleEmitDirectionY.value = properties.emitDirection.y.toFixed(2); + elParticleEmitDirectionZ.value = properties.emitDirection.z.toFixed(2); + elParticleEmitStrength.value = properties.emitStrength.toFixed(2); + elParticleLocalGravity.value = properties.localGravity.toFixed(2); + elParticleRadius.value = properties.particleRadius.toFixed(3); + } } else if (properties.type == "Web") { for (var i = 0; i < elWebSections.length; i++) { elWebSections[i].style.display = 'block'; @@ -678,6 +705,19 @@ elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff')); elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); + + elParticleMaxParticles.addEventListener('change', createEmitNumberPropertyUpdateFunction('maxParticles')); + elParticleLifeSpan.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifespan')); + elParticleEmitRate.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitRate')); + elParticleEmitDirection.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitDirection')); + var particleEmitDirectionChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( + 'emitDirection', elParticleEmitDirectionX, elParticleEmitDirectionY, elParticleEmitDirectionZ, DEGREES_TO_RADIANS); + elParticleEmitDirectionX.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitDirectionY.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitDirectionZ.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitStrength.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitStrength')); + elParticleLocalGravity.addEventListener('change', createEmitNumberPropertyUpdateFunction('localGravity')); + elParticleRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('particleRadius')); elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); @@ -1069,7 +1109,52 @@ - + +
+
Max Particles
+
+ +
+
+
+
Particle Life Span
+
+ +
+
+
+
Particle Emission Rate
+
+ +
+
+
+
Particle Emission Direction
+
+
X
+
Y
+
Z
+
+
+
+
Particle Emission Strength
+
+ +
+
+
+
Particle Local Gravity
+
+ +
+
+
+
Particle Radius
+
+ +
+
+
Model URL
From 9e121aa38749328613e19f705589a5db8782612e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sat, 23 May 2015 20:13:14 +0200 Subject: [PATCH 18/19] Fix incorrect scale constants --- libraries/octree/src/OctreeConstants.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 1246aeffd4..4a1baea2d5 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -34,9 +34,9 @@ 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 = 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 float SCALE_AT_UNREASONABLY_DEEP_RECURSION = (TREE_SCALE / powf(2.0f, UNREASONABLY_DEEP_RECURSION)); +const float SCALE_AT_DANGEROUSLY_DEEP_RECURSION = (TREE_SCALE / powf(2.0f, DANGEROUSLY_DEEP_RECURSION)); +const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = SCALE_AT_UNREASONABLY_DEEP_RECURSION * 2.0f; // 0.00001525878 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 From 18812ab25f76ec0b32e534f4f340abe193d47180 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 24 May 2015 19:18:33 +0200 Subject: [PATCH 19/19] Fix entityProperties.html undefined ref --- examples/html/entityProperties.html | 32 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index ece2da7760..7c214624c2 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -491,22 +491,7 @@ elModelAnimationFrame.value = properties.animationFrameIndex; elModelAnimationSettings.value = properties.animationSettings; elModelTextures.value = properties.textures; - elModelOriginalTextures.value = properties.originalTextures; - if (properties.type == "ParticleEffect") { - for (var i = 0; i < elParticleSections.length; i++) { - elParticleSections[i].style.display = 'block'; - } - - elParticleMaxParticles.value = properties.maxParticles; - elParticleLifeSpan.value = properties.lifespan.toFixed(2); - elParticleEmitRate.value = properties.emitRate.toFixed(1); - elParticleEmitDirectionX.value = properties.emitDirection.x.toFixed(2); - elParticleEmitDirectionY.value = properties.emitDirection.y.toFixed(2); - elParticleEmitDirectionZ.value = properties.emitDirection.z.toFixed(2); - elParticleEmitStrength.value = properties.emitStrength.toFixed(2); - elParticleLocalGravity.value = properties.localGravity.toFixed(2); - elParticleRadius.value = properties.particleRadius.toFixed(3); - } + elModelOriginalTextures.value = properties.originalTextures; } else if (properties.type == "Web") { for (var i = 0; i < elWebSections.length; i++) { elWebSections[i].style.display = 'block'; @@ -589,6 +574,20 @@ showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); showElements(document.getElementsByClassName('atmosphere-section'), elZoneBackgroundMode.value == 'atmosphere'); + } else if (properties.type == "ParticleEffect") { + for (var i = 0; i < elParticleSections.length; i++) { + elParticleSections[i].style.display = 'block'; + } + + elParticleMaxParticles.value = properties.maxParticles; + elParticleLifeSpan.value = properties.lifespan.toFixed(2); + elParticleEmitRate.value = properties.emitRate.toFixed(1); + elParticleEmitDirectionX.value = properties.emitDirection.x.toFixed(2); + elParticleEmitDirectionY.value = properties.emitDirection.y.toFixed(2); + elParticleEmitDirectionZ.value = properties.emitDirection.z.toFixed(2); + elParticleEmitStrength.value = properties.emitStrength.toFixed(2); + elParticleLocalGravity.value = properties.localGravity.toFixed(2); + elParticleRadius.value = properties.particleRadius.toFixed(3); } if (selected) { @@ -709,7 +708,6 @@ elParticleMaxParticles.addEventListener('change', createEmitNumberPropertyUpdateFunction('maxParticles')); elParticleLifeSpan.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifespan')); elParticleEmitRate.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitRate')); - elParticleEmitDirection.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitDirection')); var particleEmitDirectionChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( 'emitDirection', elParticleEmitDirectionX, elParticleEmitDirectionY, elParticleEmitDirectionZ, DEGREES_TO_RADIANS); elParticleEmitDirectionX.addEventListener('change', particleEmitDirectionChangeFunction);