diff --git a/domain-server/resources/web/index.shtml b/domain-server/resources/web/index.shtml
index bba4dc4d22..afd0af1679 100644
--- a/domain-server/resources/web/index.shtml
+++ b/domain-server/resources/web/index.shtml
@@ -12,6 +12,7 @@
Pool |
Public |
Local |
+ Uptime (s) |
Kill? |
diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js
index 18e67ac6e7..a4884486c3 100644
--- a/domain-server/resources/web/js/tables.js
+++ b/domain-server/resources/web/js/tables.js
@@ -2,16 +2,47 @@ $(document).ready(function(){
// setup a function to grab the assignments
function getNodesAndAssignments() {
$.getJSON("nodes.json", function(json){
+
+ json.nodes.sort(function(a, b){
+ if (a.type === b.type) {
+ if (a.wake_timestamp < b.wake_timestamp) {
+ return 1;
+ } else if (a.wake_timestamp > b.wake_timestamp) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (a.type === "agent" && b.type !== "agent") {
+ return 1;
+ } else if (b.type === "agent" && a.type !== "agent") {
+ return -1;
+ }
+
+ if (a.type > b.type) {
+ return 1;
+ }
+
+ if (a.type < b.type) {
+ return -1;
+ }
+ });
+
nodesTableBody = "";
- $.each(json.nodes, function (uuid, data) {
+ $.each(json.nodes, function(index, data) {
nodesTableBody += "";
nodesTableBody += "" + data.type + " | ";
- nodesTableBody += "" + uuid + " | ";
+ nodesTableBody += "" + data.uuid + " | ";
nodesTableBody += "" + (data.pool ? data.pool : "") + " | ";
nodesTableBody += "" + data.public.ip + ":" + data.public.port + " | ";
nodesTableBody += "" + data.local.ip + ":" + data.local.port + " | ";
- nodesTableBody += " | ";
+
+ var uptimeSeconds = (Date.now() - data.wake_timestamp) / 1000;
+ nodesTableBody += "" + uptimeSeconds.toLocaleString() + " | ";
+
+ nodesTableBody += " | ";
nodesTableBody += "
";
});
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index d0ac369700..af3e9a643f 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -762,10 +762,12 @@ QJsonObject DomainServer::jsonForSocket(const HifiSockAddr& socket) {
return socketJSON;
}
+const char JSON_KEY_UUID[] = "uuid";
const char JSON_KEY_TYPE[] = "type";
const char JSON_KEY_PUBLIC_SOCKET[] = "public";
const char JSON_KEY_LOCAL_SOCKET[] = "local";
const char JSON_KEY_POOL[] = "pool";
+const char JSON_KEY_WAKE_TIMESTAMP[] = "wake_timestamp";
QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
QJsonObject nodeJson;
@@ -775,6 +777,9 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
nodeTypeName = nodeTypeName.toLower();
nodeTypeName.replace(' ', '-');
+ // add the node UUID
+ nodeJson[JSON_KEY_UUID] = uuidStringWithoutCurlyBraces(node->getUUID());
+
// add the node type
nodeJson[JSON_KEY_TYPE] = nodeTypeName;
@@ -782,6 +787,9 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
nodeJson[JSON_KEY_PUBLIC_SOCKET] = jsonForSocket(node->getPublicSocket());
nodeJson[JSON_KEY_LOCAL_SOCKET] = jsonForSocket(node->getLocalSocket());
+ // add the node uptime in our list
+ nodeJson[JSON_KEY_WAKE_TIMESTAMP] = QString::number(node->getWakeTimestamp());
+
// if the node has pool information, add it
SharedAssignmentPointer matchingAssignment = _staticAssignmentHash.value(node->getUUID());
if (matchingAssignment) {
@@ -847,18 +855,17 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
} else if (url.path() == QString("%1.json").arg(URI_NODES)) {
// setup the JSON
QJsonObject rootJSON;
- QJsonObject nodesJSON;
+ QJsonArray nodesJSONArray;
// enumerate the NodeList to find the assigned nodes
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
// add the node using the UUID as the key
- QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID());
- nodesJSON[uuidString] = jsonObjectForNode(node);
+ nodesJSONArray.append(jsonObjectForNode(node));
}
- rootJSON["nodes"] = nodesJSON;
+ rootJSON["nodes"] = nodesJSONArray;
// print out the created JSON
QJsonDocument nodesDocument(rootJSON);
diff --git a/examples/collidingParticles.js b/examples/collidingParticles.js
index 2d2cf4fecc..95520df757 100644
--- a/examples/collidingParticles.js
+++ b/examples/collidingParticles.js
@@ -30,9 +30,10 @@ var gravity = {
var damping = 0.1;
var scriptA = " " +
- " function collisionWithParticle(other, penetration) { " +
+ " function collisionWithParticle(other, collision) { " +
" print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " +
- " Vec3.print('penetration=', penetration); " +
+ " Vec3.print('penetration=', collision.penetration); " +
+ " Vec3.print('contactPoint=', collision.contactPoint); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" var colorBlack = { red: 0, green: 0, blue: 0 };" +
" var otherColor = other.getColor();" +
@@ -46,9 +47,10 @@ var scriptA = " " +
" ";
var scriptB = " " +
- " function collisionWithParticle(other, penetration) { " +
+ " function collisionWithParticle(other, collision) { " +
" print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " +
- " Vec3.print('penetration=', penetration); " +
+ " Vec3.print('penetration=', collision.penetration); " +
+ " Vec3.print('contactPoint=', collision.contactPoint); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" Particle.setScript('Particle.setShouldDie(true);'); " +
" } " +
diff --git a/examples/crazylegs.js b/examples/crazylegs.js
index 099387e000..19a171dbdf 100644
--- a/examples/crazylegs.js
+++ b/examples/crazylegs.js
@@ -12,9 +12,12 @@ var AMPLITUDE = 45.0;
var cumulativeTime = 0.0;
-print("Joint List:");
+print("# Joint list start");
var jointList = MyAvatar.getJointNames();
-print(jointList);
+for (var i = 0; i < jointList.length; i++) {
+ print("jointIndex = " + jointList[i] + " = " + i);
+}
+print("# Joint list end");
Script.update.connect(function(deltaTime) {
cumulativeTime += deltaTime;
diff --git a/examples/editVoxels.js b/examples/editVoxels.js
index 4922caf0d8..1dc8c189f3 100644
--- a/examples/editVoxels.js
+++ b/examples/editVoxels.js
@@ -32,6 +32,7 @@ var MIN_PASTE_VOXEL_SCALE = .256;
var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting
var previewLineWidth = 1.5;
+var inspectJsIsRunning = false;
var isAdding = false;
var isExtruding = false;
var extrudeDirection = { x: 0, y: 0, z: 0 };
@@ -62,9 +63,9 @@ var whichColor = -1; // Starting color is 'Copy' mode
// Create sounds for adding, deleting, recoloring voxels
var addSound1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+2.raw");
-var addSound2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+3.raw");
-var addSound3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+4.raw");
+var addSound2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+4.raw");
+var addSound3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+3.raw");
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+delete+2.raw");
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+edit+2.raw");
var clickSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Switches+and+sliders/toggle+switch+-+medium.raw");
@@ -727,6 +728,9 @@ function trackKeyPressEvent(event) {
trackAsEyedropper = true;
moveTools();
}
+ if (event.text == "ALT") {
+ inspectJsIsRunning = true;
+ }
showPreviewGuides();
}
@@ -739,6 +743,10 @@ function trackKeyReleaseEvent(event) {
showPreviewGuides();
Audio.playSound(clickSound, audioOptions);
}
+
+ if (event.text == "ALT") {
+ inspectJsIsRunning = false;
+ }
if (editToolsOn) {
if (event.text == "ESC") {
@@ -777,11 +785,13 @@ function trackKeyReleaseEvent(event) {
}
function mousePressEvent(event) {
-
// if our tools are off, then don't do anything
if (!editToolsOn) {
return;
}
+ if (inspectJsIsRunning) {
+ return;
+ }
var clickedOnSomething = false;
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
@@ -1061,7 +1071,9 @@ function mouseMoveEvent(event) {
if (!editToolsOn) {
return;
}
-
+ if (inspectJsIsRunning) {
+ return;
+ }
if (isMovingSlider) {
thumbX = (event.x - thumbClickOffsetX) - sliderX;
@@ -1121,7 +1133,10 @@ function mouseReleaseEvent(event) {
if (!editToolsOn) {
return;
}
-
+ if (inspectJsIsRunning) {
+ return;
+ }
+
if (isMovingSlider) {
isMovingSlider = false;
}
@@ -1214,24 +1229,6 @@ function moveTools() {
}
-function touchBeginEvent(event) {
- if (!editToolsOn) {
- return;
- }
-}
-
-function touchUpdateEvent(event) {
- if (!editToolsOn) {
- return;
- }
-}
-
-function touchEndEvent(event) {
- if (!editToolsOn) {
- return;
- }
-}
-
var lastFingerAddVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area
var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able area
@@ -1332,9 +1329,6 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
-Controller.touchBeginEvent.connect(touchBeginEvent);
-Controller.touchUpdateEvent.connect(touchUpdateEvent);
-Controller.touchEndEvent.connect(touchEndEvent);
Controller.captureKeyEvents({ text: "+" });
Controller.captureKeyEvents({ text: "-" });
diff --git a/examples/globalCollisionsExample.js b/examples/globalCollisionsExample.js
index 266823f564..7abf707cbf 100644
--- a/examples/globalCollisionsExample.js
+++ b/examples/globalCollisionsExample.js
@@ -12,18 +12,20 @@
print("hello...");
-function particleCollisionWithVoxel(particle, voxel, penetration) {
+function particleCollisionWithVoxel(particle, voxel, collision) {
print("particleCollisionWithVoxel()..");
print(" particle.getID()=" + particle.id);
print(" voxel color...=" + voxel.red + ", " + voxel.green + ", " + voxel.blue);
- Vec3.print('penetration=', penetration);
+ Vec3.print('penetration=', collision.penetration);
+ Vec3.print('contactPoint=', collision.contactPoint);
}
-function particleCollisionWithParticle(particleA, particleB, penetration) {
+function particleCollisionWithParticle(particleA, particleB, collision) {
print("particleCollisionWithParticle()..");
print(" particleA.getID()=" + particleA.id);
print(" particleB.getID()=" + particleB.id);
- Vec3.print('penetration=', penetration);
+ Vec3.print('penetration=', collision.penetration);
+ Vec3.print('contactPoint=', collision.contactPoint);
}
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
diff --git a/examples/gun.js b/examples/gun.js
index e358e6b391..7bdde19d94 100644
--- a/examples/gun.js
+++ b/examples/gun.js
@@ -145,24 +145,21 @@ function shootTarget() {
-function particleCollisionWithVoxel(particle, voxel, penetration) {
+function particleCollisionWithVoxel(particle, voxel, collision) {
var HOLE_SIZE = 0.125;
var particleProperties = Particles.getParticleProperties(particle);
var position = particleProperties.position;
Particles.deleteParticle(particle);
// Make a hole in this voxel
- Vec3.print("penetration", penetration);
- Vec3.print("position", position);
- var pointOfEntry = Vec3.subtract(position, penetration);
- Vec3.print("pointOfEntry", pointOfEntry);
- Voxels.eraseVoxel(pointOfEntry.x, pointOfEntry.y, pointOfEntry.z, HOLE_SIZE);
+ Vec3.print("penetration", collision.penetration);
+ Vec3.print("contactPoint", collision.contactPoint);
+ Voxels.eraseVoxel(contactPoint.x, contactPoint.y, contactPoint.z, HOLE_SIZE);
Voxels.eraseVoxel(position.x, position.y, position.z, HOLE_SIZE);
- //audioOptions.position = position;
audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
Audio.playSound(impactSound, audioOptions);
}
-function particleCollisionWithParticle(particle1, particle2) {
+function particleCollisionWithParticle(particle1, particle2, collision) {
score++;
if (showScore) {
Overlays.editOverlay(text, { text: "Score: " + score } );
@@ -174,9 +171,11 @@ function particleCollisionWithParticle(particle1, particle2) {
var endTime = new Date();
var msecs = endTime.valueOf() - shotTime.valueOf();
print("hit, msecs = " + msecs);
+ Vec3.print("penetration = ", collision.penetration);
+ Vec3.print("contactPoint = ", collision.contactPoint);
Particles.deleteParticle(particle1);
Particles.deleteParticle(particle2);
- audioOptions.position = newPosition;
+ // play the sound near the camera so the shooter can hear it
audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
Audio.playSound(targetHitSound, audioOptions);
}
diff --git a/examples/paintGun.js b/examples/paintGun.js
index 6b6e78b43e..0b30d99fb5 100644
--- a/examples/paintGun.js
+++ b/examples/paintGun.js
@@ -62,9 +62,10 @@ function checkController(deltaTime) {
// This is the script for the particles that this gun shoots.
var script =
- " function collisionWithVoxel(voxel, penetration) { " +
+ " function collisionWithVoxel(voxel, collision) { " +
" print('collisionWithVoxel(voxel)... '); " +
- " Vec3.print('penetration=', penetration); " +
+ " Vec3.print('penetration=', collision.penetration); " +
+ " Vec3.print('contactPoint=', collision.contactPoint); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" +
" var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" +
diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js
index 61ff93fc8f..df985e2e18 100644
--- a/examples/spaceInvadersExample.js
+++ b/examples/spaceInvadersExample.js
@@ -392,9 +392,10 @@ function deleteIfInvader(possibleInvaderParticle) {
}
}
-function particleCollisionWithParticle(particleA, particleB, penetration) {
+function particleCollisionWithParticle(particleA, particleB, collision) {
print("particleCollisionWithParticle() a.id="+particleA.id + " b.id=" + particleB.id);
- Vec3.print('particleCollisionWithParticle() penetration=', penetration);
+ Vec3.print('particleCollisionWithParticle() penetration=', collision.penetration);
+ Vec3.print('particleCollisionWithParticle() contactPoint=', collision.contactPoint);
if (missileFired) {
myMissile = Particles.identifyParticle(myMissile);
if (myMissile.id == particleA.id) {
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index cfe920bf40..a69833dd84 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -1577,14 +1577,14 @@ void Application::init() {
// connect the _particleCollisionSystem to our script engine's ParticleScriptingInterface
connect(&_particleCollisionSystem,
- SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)),
+ SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const CollisionInfo&)),
ScriptEngine::getParticlesScriptingInterface(),
- SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)));
+ SIGNAL(particleCollisionWithVoxels(const ParticleID&, const VoxelDetail&, const CollisionInfo&)));
connect(&_particleCollisionSystem,
- SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)),
+ SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const CollisionInfo&)),
ScriptEngine::getParticlesScriptingInterface(),
- SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)));
+ SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const CollisionInfo&)));
_audio.init(_glWidget);
diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp
index 899514d1c1..41f26258ff 100644
--- a/interface/src/avatar/Avatar.cpp
+++ b/interface/src/avatar/Avatar.cpp
@@ -46,7 +46,6 @@ Avatar::Avatar() :
_mode(AVATAR_MODE_STANDING),
_velocity(0.0f, 0.0f, 0.0f),
_thrust(0.0f, 0.0f, 0.0f),
- _speed(0.0f),
_leanScale(0.5f),
_scale(1.0f),
_worldUpDirection(DEFAULT_UP_DIRECTION),
@@ -137,7 +136,8 @@ void Avatar::simulate(float deltaTime) {
}
// use speed and angular velocity to determine walking vs. standing
- if (_speed + fabs(_bodyYawDelta) > 0.2) {
+ float speed = glm::length(_velocity);
+ if (speed + fabs(_bodyYawDelta) > 0.2) {
_mode = AVATAR_MODE_WALKING;
} else {
_mode = AVATAR_MODE_INTERACTING;
@@ -331,6 +331,10 @@ void Avatar::renderBody(RenderMode renderMode) {
getHand()->render(false);
}
+void Avatar::updateJointMappings() {
+ // no-op; joint mappings come from skeleton model
+}
+
void Avatar::renderBillboard() {
if (_billboard.isEmpty()) {
return;
diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h
index f6d5669859..f57982b514 100755
--- a/interface/src/avatar/Avatar.h
+++ b/interface/src/avatar/Avatar.h
@@ -160,7 +160,6 @@ protected:
AvatarMode _mode;
glm::vec3 _velocity;
glm::vec3 _thrust;
- float _speed;
float _leanScale;
float _scale;
glm::vec3 _worldUpDirection;
@@ -187,6 +186,8 @@ protected:
void renderDisplayName();
virtual void renderBody(RenderMode renderMode);
+ virtual void updateJointMappings();
+
private:
bool _initialized;
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index 99cff79244..acc4362d36 100644
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -169,9 +169,6 @@ void MyAvatar::simulate(float deltaTime) {
// Collect thrust forces from keyboard and devices
updateThrust(deltaTime);
- // calculate speed
- _speed = glm::length(_velocity);
-
// update the movement of the hand and process handshaking with other avatars...
updateHandMovementAndTouching(deltaTime);
@@ -203,9 +200,9 @@ void MyAvatar::simulate(float deltaTime) {
if (fabs(_bodyRollDelta) < MINIMUM_ROTATION_RATE) { _bodyRollDelta = 0.f; }
if (fabs(_bodyPitchDelta) < MINIMUM_ROTATION_RATE) { _bodyPitchDelta = 0.f; }
- const float MAX_STATIC_FRICTION_VELOCITY = 0.5f;
+ const float MAX_STATIC_FRICTION_SPEED = 0.5f;
const float STATIC_FRICTION_STRENGTH = _scale * 20.f;
- applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH);
+ applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_SPEED, STATIC_FRICTION_STRENGTH);
// Damp avatar velocity
const float LINEAR_DAMPING_STRENGTH = 0.5f;
@@ -230,7 +227,8 @@ void MyAvatar::simulate(float deltaTime) {
const float WALKING_SPEED_THRESHOLD = 0.2f;
// use speed and angular velocity to determine walking vs. standing
- if (_speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) {
+ float speed = glm::length(_velocity);
+ if (speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) {
_mode = AVATAR_MODE_WALKING;
} else {
_mode = AVATAR_MODE_INTERACTING;
@@ -238,7 +236,7 @@ void MyAvatar::simulate(float deltaTime) {
// update moving flag based on speed
const float MOVING_SPEED_THRESHOLD = 0.01f;
- _moving = _speed > MOVING_SPEED_THRESHOLD;
+ _moving = speed > MOVING_SPEED_THRESHOLD;
// If a move target is set, update position explicitly
const float MOVE_FINISHED_TOLERANCE = 0.1f;
@@ -681,7 +679,6 @@ void MyAvatar::updateThrust(float deltaTime) {
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
const float THRUST_INCREASE_RATE = 1.05f;
const float MAX_THRUST_MULTIPLIER = 75.0f;
- //printf("m = %.3f\n", _thrustMultiplier);
_thrustMultiplier *= 1.f + deltaTime * THRUST_INCREASE_RATE;
if (_thrustMultiplier > MAX_THRUST_MULTIPLIER) {
_thrustMultiplier = MAX_THRUST_MULTIPLIER;
@@ -703,11 +700,12 @@ void MyAvatar::updateThrust(float deltaTime) {
if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) {
_speedBrakes = true;
}
+ _isThrustOn = (glm::length(_thrust) > EPSILON);
- if (_speedBrakes && (glm::length(_velocity) < MIN_SPEED_BRAKE_VELOCITY)) {
+ if (_isThrustOn || (_speedBrakes && (glm::length(_velocity) < MIN_SPEED_BRAKE_VELOCITY))) {
_speedBrakes = false;
}
- _isThrustOn = (glm::length(_thrust) > EPSILON);
+
}
void MyAvatar::updateHandMovementAndTouching(float deltaTime) {
diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h
index 5c940f0f50..2125b126b3 100644
--- a/interface/src/avatar/MyAvatar.h
+++ b/interface/src/avatar/MyAvatar.h
@@ -50,7 +50,6 @@ public:
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; }
// getters
- float getSpeed() const { return _speed; }
AvatarMode getMode() const { return _mode; }
float getLeanScale() const { return _leanScale; }
float getElapsedTimeStopped() const { return _elapsedTimeStopped; }
diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp
index 1722732e76..dbcbb3d8bb 100644
--- a/interface/src/ui/Stats.cpp
+++ b/interface/src/ui/Stats.cpp
@@ -20,6 +20,8 @@
#include "Menu.h"
#include "Util.h"
+using namespace std;
+
const int STATS_PELS_PER_LINE = 20;
const int STATS_GENERAL_MIN_WIDTH = 165;
@@ -287,7 +289,7 @@ void Stats::display(
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
glm::vec3 avatarPos = myAvatar->getPosition();
- lines = _expanded ? 4 : 3;
+ lines = _expanded ? 5 : 3;
drawBackground(backgroundColor, horizontalOffset, 0, _geoStatsWidth, lines * STATS_PELS_PER_LINE + 10);
horizontalOffset += 5;
@@ -318,6 +320,16 @@ void Stats::display(
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarMixerStats, color);
+
+ stringstream downloads;
+ downloads << "Downloads: ";
+ foreach (Resource* resource, ResourceCache::getLoadingRequests()) {
+ downloads << (int)(resource->getProgress() * 100.0f) << "% ";
+ }
+ downloads << "(" << ResourceCache::getPendingRequestCount() << " pending)";
+
+ verticalOffset += STATS_PELS_PER_LINE;
+ drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, downloads.str().c_str(), color);
}
verticalOffset = 0;
diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp
index 930e3f7350..e84636b5a4 100644
--- a/libraries/avatars/src/AvatarData.cpp
+++ b/libraries/avatars/src/AvatarData.cpp
@@ -639,6 +639,8 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_BODY_MODEL_URL : skeletonModelURL;
qDebug() << "Changing skeleton model for avatar to" << _skeletonModelURL.toString();
+
+ updateJointMappings();
}
void AvatarData::setDisplayName(const QString& displayName) {
@@ -673,6 +675,40 @@ void AvatarData::setBillboardFromURL(const QString &billboardURL) {
void AvatarData::setBillboardFromNetworkReply() {
QNetworkReply* networkReply = reinterpret_cast(sender());
setBillboard(networkReply->readAll());
+ networkReply->deleteLater();
+}
+
+void AvatarData::setJointMappingsFromNetworkReply() {
+ QNetworkReply* networkReply = static_cast(sender());
+
+ QByteArray line;
+ while (!(line = networkReply->readLine()).isEmpty()) {
+ if (!(line = line.trimmed()).startsWith("jointIndex")) {
+ continue;
+ }
+ int jointNameIndex = line.indexOf('=') + 1;
+ if (jointNameIndex == 0) {
+ continue;
+ }
+ int secondSeparatorIndex = line.indexOf('=', jointNameIndex);
+ if (secondSeparatorIndex == -1) {
+ continue;
+ }
+ QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed();
+ bool ok;
+ int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok);
+ if (ok) {
+ while (_jointNames.size() < jointIndex + 1) {
+ _jointNames.append(QString());
+ }
+ _jointNames[jointIndex] = jointName;
+ }
+ }
+ for (int i = 0; i < _jointNames.size(); i++) {
+ _jointIndices.insert(_jointNames.at(i), i + 1);
+ }
+
+ networkReply->deleteLater();
}
void AvatarData::setClampedTargetScale(float targetScale) {
@@ -705,3 +741,13 @@ void AvatarData::sendBillboardPacket() {
NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
}
}
+
+void AvatarData::updateJointMappings() {
+ _jointIndices.clear();
+ _jointNames.clear();
+
+ if (networkAccessManager && _skeletonModelURL.fileName().toLower().endsWith(".fst")) {
+ QNetworkReply* networkReply = networkAccessManager->get(QNetworkRequest(_skeletonModelURL));
+ connect(networkReply, SIGNAL(finished()), this, SLOT(setJointMappingsFromNetworkReply()));
+ }
+}
diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h
index 221bbd0428..cf645855e8 100755
--- a/libraries/avatars/src/AvatarData.h
+++ b/libraries/avatars/src/AvatarData.h
@@ -30,6 +30,7 @@ typedef unsigned long long quint64;
#include
#include
+#include
#include
#include
#include
@@ -160,9 +161,9 @@ public:
Q_INVOKABLE glm::quat getJointRotation(const QString& name) const;
/// Returns the index of the joint with the specified name, or -1 if not found/unknown.
- Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return -1; }
+ Q_INVOKABLE virtual int getJointIndex(const QString& name) const { return _jointIndices.value(name) - 1; }
- Q_INVOKABLE virtual QStringList getJointNames() const { return QStringList(); }
+ Q_INVOKABLE virtual QStringList getJointNames() const { return _jointNames; }
// key state
void setKeyState(KeyState s) { _keyState = s; }
@@ -217,6 +218,7 @@ public slots:
void sendIdentityPacket();
void sendBillboardPacket();
void setBillboardFromNetworkReply();
+ void setJointMappingsFromNetworkReply();
protected:
glm::vec3 _position;
glm::vec3 _handPosition;
@@ -258,10 +260,16 @@ protected:
QByteArray _billboard;
QString _billboardURL;
+ QHash _jointIndices; ///< 1-based, since zero is returned for missing keys
+ QStringList _jointNames; ///< in order of depth-first traversal
+
static QNetworkAccessManager* networkAccessManager;
quint64 _errorLogExpiry; ///< time in future when to log an error
+ /// Loads the joint indices, names from the FST file (if any)
+ virtual void updateJointMappings();
+
private:
// privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&);
diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp
index c827e28c78..028cf80df9 100644
--- a/libraries/particles/src/ParticleCollisionSystem.cpp
+++ b/libraries/particles/src/ParticleCollisionSystem.cpp
@@ -72,17 +72,17 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) {
}
void ParticleCollisionSystem::emitGlobalParticleCollisionWithVoxel(Particle* particle,
- VoxelDetail* voxelDetails, const glm::vec3& penetration) {
+ VoxelDetail* voxelDetails, const CollisionInfo& collision) {
ParticleID particleID = particle->getParticleID();
- emit particleCollisionWithVoxel(particleID, *voxelDetails, penetration);
+ emit particleCollisionWithVoxel(particleID, *voxelDetails, collision);
}
void ParticleCollisionSystem::emitGlobalParticleCollisionWithParticle(Particle* particleA,
- Particle* particleB, const glm::vec3& penetration) {
+ Particle* particleB, const CollisionInfo& collision) {
ParticleID idA = particleA->getParticleID();
ParticleID idB = particleB->getParticleID();
- emit particleCollisionWithParticle(idA, idB, penetration);
+ emit particleCollisionWithParticle(idA, idB, collision);
}
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
@@ -100,11 +100,17 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
// let the particles run their collision scripts if they have them
particle->collisionWithVoxel(voxelDetails, collisionInfo._penetration);
- // let the global script run their collision scripts for particles if they have them
- emitGlobalParticleCollisionWithVoxel(particle, voxelDetails, collisionInfo._penetration);
-
+ // findSpherePenetration() only computes the penetration but we also want some other collision info
+ // so we compute it ourselves here. Note that we must multiply scale by TREE_SCALE when feeding
+ // the results to systems outside of this octree reference frame.
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
+ collisionInfo._contactPoint = (float)TREE_SCALE * (particle->getPosition() + particle->getRadius() * glm::normalize(collisionInfo._penetration));
+ // let the global script run their collision scripts for particles if they have them
+ emitGlobalParticleCollisionWithVoxel(particle, voxelDetails, collisionInfo);
+
+ // we must scale back down to the octree reference frame before updating the particle properties
collisionInfo._penetration /= (float)(TREE_SCALE);
+ collisionInfo._contactPoint /= (float)(TREE_SCALE);
particle->applyHardCollision(collisionInfo);
queueParticlePropertiesUpdate(particle);
@@ -121,8 +127,7 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
glm::vec3 penetration;
Particle* particleB;
if (_particles->findSpherePenetration(center, radius, penetration, (void**)&particleB, Octree::NoLock)) {
- // NOTE: 'penetration' is the depth that 'particleA' overlaps 'particleB'.
- // That is, it points from A into B.
+ // NOTE: 'penetration' is the depth that 'particleA' overlaps 'particleB'. It points from A into B.
// Even if the particles overlap... when the particles are already moving appart
// we don't want to count this as a collision.
@@ -130,7 +135,12 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
if (glm::dot(relativeVelocity, penetration) > 0.0f) {
particleA->collisionWithParticle(particleB, penetration);
particleB->collisionWithParticle(particleA, penetration * -1.0f); // the penetration is reversed
- emitGlobalParticleCollisionWithParticle(particleA, particleB, penetration);
+
+ CollisionInfo collision;
+ collision._penetration = penetration;
+ // for now the contactPoint is the average between the the two paricle centers
+ collision._contactPoint = (0.5f * (float)TREE_SCALE) * (particleA->getPosition() + particleB->getPosition());
+ emitGlobalParticleCollisionWithParticle(particleA, particleB, collision);
glm::vec3 axis = glm::normalize(penetration);
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
@@ -142,25 +152,25 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
float massB = (particleB->getInHand()) ? MAX_MASS : particleB->getMass();
float totalMass = massA + massB;
- // handle A particle
+ // handle particle A
particleA->setVelocity(particleA->getVelocity() - axialVelocity * (2.0f * massB / totalMass));
particleA->setPosition(particleA->getPosition() - 0.5f * penetration);
ParticleProperties propertiesA;
- ParticleID particleAid(particleA->getID());
+ ParticleID idA(particleA->getID());
propertiesA.copyFromParticle(*particleA);
propertiesA.setVelocity(particleA->getVelocity() * (float)TREE_SCALE);
propertiesA.setPosition(particleA->getPosition() * (float)TREE_SCALE);
- _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, particleAid, propertiesA);
+ _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, idA, propertiesA);
- // handle B particle
+ // handle particle B
particleB->setVelocity(particleB->getVelocity() + axialVelocity * (2.0f * massA / totalMass));
particleA->setPosition(particleB->getPosition() + 0.5f * penetration);
ParticleProperties propertiesB;
- ParticleID particleBid(particleB->getID());
+ ParticleID idB(particleB->getID());
propertiesB.copyFromParticle(*particleB);
propertiesB.setVelocity(particleB->getVelocity() * (float)TREE_SCALE);
propertiesB.setPosition(particleB->getPosition() * (float)TREE_SCALE);
- _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, particleBid, propertiesB);
+ _packetSender->queueParticleEditMessage(PacketTypeParticleAddOrEdit, idB, propertiesB);
_packetSender->releaseQueuedMessages();
diff --git a/libraries/particles/src/ParticleCollisionSystem.h b/libraries/particles/src/ParticleCollisionSystem.h
index 1b30fd31ac..c6ab97c02b 100644
--- a/libraries/particles/src/ParticleCollisionSystem.h
+++ b/libraries/particles/src/ParticleCollisionSystem.h
@@ -53,13 +53,13 @@ public:
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
signals:
- void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const glm::vec3& penetration);
- void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration);
+ void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const CollisionInfo& penetration);
+ void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const CollisionInfo& penetration);
private:
static bool updateOperation(OctreeElement* element, void* extraData);
- void emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails, const glm::vec3& penetration);
- void emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB, const glm::vec3& penetration);
+ void emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails, const CollisionInfo& penetration);
+ void emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB, const CollisionInfo& penetration);
ParticleEditPacketSender* _packetSender;
ParticleTree* _particles;
diff --git a/libraries/particles/src/ParticlesScriptingInterface.h b/libraries/particles/src/ParticlesScriptingInterface.h
index af5f76a6af..8de44e20bb 100644
--- a/libraries/particles/src/ParticlesScriptingInterface.h
+++ b/libraries/particles/src/ParticlesScriptingInterface.h
@@ -11,6 +11,8 @@
#include
+#include
+
#include
#include "ParticleEditPacketSender.h"
@@ -27,17 +29,6 @@ public:
void setParticleTree(ParticleTree* particleTree) { _particleTree = particleTree; }
ParticleTree* getParticleTree(ParticleTree*) { return _particleTree; }
-private slots:
- /// inbound slots for external collision systems
- void forwardParticleCollisionWithVoxel(const ParticleID& particleID,
- const VoxelDetail& voxel, const glm::vec3& penetration) {
- emit particleCollisionWithVoxel(particleID, voxel, penetration);
- }
-
- void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration) {
- emit particleCollisionWithParticle(idA, idB, penetration);
- }
-
public slots:
/// adds a particle with the specific properties
ParticleID addParticle(const ParticleProperties& properties);
@@ -66,8 +57,8 @@ public slots:
QVector findParticles(const glm::vec3& center, float radius) const;
signals:
- void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const glm::vec3& penetration);
- void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration);
+ void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const CollisionInfo& collision);
+ void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const CollisionInfo& collision);
private:
void queueParticleMessage(PacketType packetType, ParticleID particleID, const ParticleProperties& properties);
diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp
index a4491fb707..1e78bc3feb 100644
--- a/libraries/shared/src/Node.cpp
+++ b/libraries/shared/src/Node.cpp
@@ -19,6 +19,7 @@
#include "SharedUtil.h"
#include
+#include
#include
const QString UNKNOWN_NodeType_t_NAME = "Unknown";
@@ -47,7 +48,7 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) {
Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) :
_type(type),
_uuid(uuid),
- _wakeMicrostamp(usecTimestampNow()),
+ _wakeTimestamp(QDateTime::currentMSecsSinceEpoch()),
_lastHeardMicrostamp(usecTimestampNow()),
_publicSocket(publicSocket),
_localSocket(localSocket),
diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h
index 79d75629a6..5d30d6f7b0 100644
--- a/libraries/shared/src/Node.h
+++ b/libraries/shared/src/Node.h
@@ -60,8 +60,8 @@ public:
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
- quint64 getWakeMicrostamp() const { return _wakeMicrostamp; }
- void setWakeMicrostamp(quint64 wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; }
+ quint64 getWakeTimestamp() const { return _wakeTimestamp; }
+ void setWakeTimestamp(quint64 wakeTimestamp) { _wakeTimestamp = wakeTimestamp; }
quint64 getLastHeardMicrostamp() const { return _lastHeardMicrostamp; }
void setLastHeardMicrostamp(quint64 lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; }
@@ -109,7 +109,7 @@ private:
NodeType_t _type;
QUuid _uuid;
- quint64 _wakeMicrostamp;
+ quint64 _wakeTimestamp;
quint64 _lastHeardMicrostamp;
HifiSockAddr _publicSocket;
HifiSockAddr _localSocket;
diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp
index d106977ae0..af074c59bc 100644
--- a/libraries/shared/src/RegisteredMetaTypes.cpp
+++ b/libraries/shared/src/RegisteredMetaTypes.cpp
@@ -16,6 +16,7 @@ static int vec2MetaTypeId = qRegisterMetaType();
static int quatMetaTypeId = qRegisterMetaType();
static int xColorMetaTypeId = qRegisterMetaType();
static int pickRayMetaTypeId = qRegisterMetaType();
+static int collisionMetaTypeId = qRegisterMetaType();
void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
@@ -24,6 +25,7 @@ void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue);
qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue);
qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue);
+ qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
}
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) {
@@ -122,3 +124,14 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) {
}
}
+QScriptValue collisionToScriptValue(QScriptEngine* engine, const CollisionInfo& collision) {
+ QScriptValue obj = engine->newObject();
+ obj.setProperty("penetration", vec3toScriptValue(engine, collision._penetration));
+ obj.setProperty("contactPoint", vec3toScriptValue(engine, collision._contactPoint));
+ return obj;
+}
+
+void collisionFromScriptValue(const QScriptValue &object, CollisionInfo& collision) {
+ // TODO: implement this when we know what it means to accept collision events from JS
+}
+
diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h
index ea65e45c95..0e7732c057 100644
--- a/libraries/shared/src/RegisteredMetaTypes.h
+++ b/libraries/shared/src/RegisteredMetaTypes.h
@@ -15,6 +15,7 @@
#include
+#include "CollisionInfo.h"
#include "SharedUtil.h"
Q_DECLARE_METATYPE(glm::vec4)
@@ -50,4 +51,8 @@ Q_DECLARE_METATYPE(PickRay)
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
+Q_DECLARE_METATYPE(CollisionInfo)
+QScriptValue collisionToScriptValue(QScriptEngine* engine, const CollisionInfo& collision);
+void collisionFromScriptValue(const QScriptValue &object, CollisionInfo& collision);
+
#endif