Merge branch 'master' of https://github.com/highfidelity/hifi into pull_out_menu_mess

This commit is contained in:
Atlante45 2015-01-20 17:41:08 -08:00
commit e1725d1eee
14 changed files with 349 additions and 113 deletions

View file

@ -311,7 +311,7 @@ MetavoxelPersister::MetavoxelPersister(MetavoxelServer* server) :
const char* SAVE_FILE = "/resources/metavoxels.dat";
const int FILE_MAGIC = 0xDADAFACE;
const int FILE_VERSION = 3;
const int FILE_VERSION = 4;
void MetavoxelPersister::load() {
QString path = QCoreApplication::applicationDirPath() + SAVE_FILE;

197
examples/billiards.js Normal file
View file

@ -0,0 +1,197 @@
// Pool Table
var tableParts = [];
var balls = [];
var LENGTH = 2.84;
var WIDTH = 1.42;
var HEIGHT = 0.80;
var SCALE = 2.0;
var BALL_SIZE = 0.05715;
var BUMPER_WIDTH = 0.15;
var BUMPER_HEIGHT = BALL_SIZE * 2.0;
var HOLE_SIZE = BALL_SIZE;
var DROP_HEIGHT = BALL_SIZE * 3.0;
var GRAVITY = -9.8;
var BALL_GAP = 0.001;
var startStroke = 0;
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var screenSize = Controller.getViewportDimensions();
var reticle = Overlays.addOverlay("image", {
x: screenSize.x / 2 - 16,
y: screenSize.y / 2 - 16,
width: 32,
height: 32,
imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png",
color: { red: 255, green: 255, blue: 255},
alpha: 1
});
function makeTable(pos) {
// Top
tableParts.push(Entities.addEntity(
{ type: "Box",
position: pos,
dimensions: { x: LENGTH * SCALE, y: HEIGHT, z: WIDTH * SCALE },
color: { red: 0, green: 255, blue: 0 } }));
// Long Bumpers
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x - LENGTH / 2.0,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x + LENGTH / 2.0,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x - LENGTH / 2.0,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x + LENGTH / 2.0,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
// End bumpers
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x + (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z },
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
tableParts.push(Entities.addEntity(
{ type: "Box",
position: { x: pos.x - (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
z: pos.z },
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
color: { red: 237, green: 201, blue: 175 } }));
}
function makeBalls(pos) {
var colors = [{ red: 255, green: 255, blue: 0}, // Yellow
{ red: 0, green: 0, blue: 255}, // Blue
{ red: 255, green: 0, blue: 0}, // Red
{ red: 128, green: 0, blue: 128}, // Purple
{ red: 255, green: 165, blue: 0}, // Orange
{ red: 0, green: 255, blue: 0}, // Green
{ red: 128, green: 0, blue: 0}, // Maroon
{ red: 0, green: 0, blue: 0}, // Black
{ red: 255, green: 255, blue: 224}, // Light Yellow
{ red: 173, green: 216, blue: 230}, // Light Blue
{ red: 205, green: 92, blue: 92}, // Indian Red
{ red: 218, green: 112, blue: 214}, // Orchid
{ red: 218, green: 165, blue: 32}, // GoldenRod
{ red: 255, green: 99, blue: 71}, // Tomato
{ red: 128, green: 128, blue: 128}]; // Gray
// Object balls
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
for (var row = 1; row <= 5; row++) {
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
for (var spot = 0; spot < row; spot++) {
balls.push(Entities.addEntity(
{ type: "Sphere",
position: ballPosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: colors[balls.length],
gravity: { x: 0, y: GRAVITY, z: 0 },
ignoreCollisions: false,
damping: 0.40,
collisionsWillMove: true }));
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
}
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
}
// Cue Ball
ballPosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
balls.push(Entities.addEntity(
{ type: "Sphere",
position: ballPosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: { red: 255, green: 255, blue: 255 },
gravity: { x: 0, y: GRAVITY, z: 0 },
ignoreCollisions: false,
damping: 0.40,
collisionsWillMove: true }));
}
function shootCue(velocity) {
var DISTANCE_FROM_CAMERA = BALL_SIZE * 5.0 * SCALE;
var camera = Camera.getPosition();
var forwardVector = Quat.getFront(Camera.getOrientation());
var cuePosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
var velocity = Vec3.multiply(forwardVector, velocity);
var BULLET_LIFETIME = 3.0;
var BULLET_GRAVITY = 0.0;
bulletID = Entities.addEntity(
{ type: "Sphere",
position: cuePosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: { red: 255, green: 255, blue: 255 },
velocity: velocity,
lifetime: BULLET_LIFETIME,
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
damping: 0.10,
density: 1000,
ignoreCollisions: false,
collisionsWillMove: true
});
}
function keyReleaseEvent(event) {
if ((startStroke > 0) && event.text == "SPACE") {
var endTime = new Date().getTime();
var delta = endTime - startStroke;
shootCue(delta / 100.0);
startStroke = 0;
}
}
function keyPressEvent(event) {
// Fire a cue ball
if ((startStroke == 0) && (event.text == "SPACE")) {
startStroke = new Date().getTime();
}
}
function cleanup() {
for (var i = 0; i < tableParts.length; i++) {
if (!tableParts[i].isKnownID) {
tableParts[i] = Entities.identifyEntity(tableParts[i]);
}
Entities.deleteEntity(tableParts[i]);
}
for (var i = 0; i < balls.length; i++) {
if (!balls[i].isKnownID) {
balls[i] = Entities.identifyEntity(balls[i]);
}
Entities.deleteEntity(balls[i]);
}
Overlays.deleteOverlay(reticle);
}
var tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
makeTable(tableCenter);
makeBalls(tableCenter);
Script.scriptEnding.connect(cleanup);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);

View file

@ -22,7 +22,8 @@ varying vec4 alphaValues;
void main(void) {
// blend the splat textures
gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
gl_FragColor = vec4(gl_Color.rgb, step(1.0, gl_Color.a + 1.0 / 512.0)) *
(texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x +
texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y +
texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z +
texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w);

View file

@ -228,7 +228,12 @@ unsigned int Overlays::cloneOverlay(unsigned int id) {
} else if (_overlaysWorld.contains(id)) {
thisOverlay = _overlaysWorld[id];
}
return addOverlay(thisOverlay->createClone());
if (thisOverlay) {
return addOverlay(thisOverlay->createClone());
}
return 0; // Not found
}
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {

View file

@ -2432,12 +2432,13 @@ void MappedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
}
QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
bool reread = (object != NULL);
if (!object && _metaObject) {
object = _metaObject->newInstance();
}
foreach (const StreamerPropertyPair& property, _properties) {
QVariant value = property.first->read(in);
if (property.second.isValid() && object) {
if (property.second.isValid() && object && !reread) {
property.second.write(object, value);
}
}
@ -2445,6 +2446,7 @@ QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const {
}
QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
bool reread = (object != NULL);
if (!object && _metaObject) {
object = _metaObject->newInstance();
}
@ -2452,7 +2454,7 @@ QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* refere
QVariant value;
property.first->readDelta(in, value, (property.second.isValid() && reference &&
reference->metaObject() == _metaObject) ? property.second.read(reference) : QVariant());
if (property.second.isValid() && object) {
if (property.second.isValid() && object && !reread) {
property.second.write(object, value);
}
}
@ -2475,13 +2477,13 @@ void SharedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
QObject* SharedObjectStreamer::read(Bitstream& in, QObject* object) const {
QObject* result = MappedObjectStreamer::read(in, object);
static_cast<SharedObject*>(result)->readExtra(in);
static_cast<SharedObject*>(result)->readExtra(in, object != NULL);
return result;
}
QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
QObject* result = MappedObjectStreamer::readRawDelta(in, reference, object);
static_cast<SharedObject*>(result)->readExtraDelta(in, static_cast<const SharedObject*>(reference));
static_cast<SharedObject*>(result)->readExtraDelta(in, static_cast<const SharedObject*>(reference), object != NULL);
return result;
}
@ -2592,6 +2594,7 @@ void GenericObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object,
}
QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
bool reread = (object != NULL);
if (!object) {
object = new GenericSharedObject(_weakSelf);
}
@ -2599,11 +2602,14 @@ QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const {
foreach (const StreamerNamePair& property, _properties) {
values.append(property.first->read(in));
}
static_cast<GenericSharedObject*>(object)->setValues(values);
if (!reread) {
static_cast<GenericSharedObject*>(object)->setValues(values);
}
return object;
}
QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const {
bool reread = (object != NULL);
if (!object) {
object = new GenericSharedObject(_weakSelf);
}
@ -2615,7 +2621,9 @@ QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* refer
static_cast<const GenericSharedObject*>(reference)->getValues().at(i) : QVariant());
values.append(value);
}
static_cast<GenericSharedObject*>(object)->setValues(values);
if (!reread) {
static_cast<GenericSharedObject*>(object)->setValues(values);
}
return object;
}

View file

@ -135,7 +135,7 @@ void SharedObject::writeExtra(Bitstream& out) const {
// nothing by default
}
void SharedObject::readExtra(Bitstream& in) {
void SharedObject::readExtra(Bitstream& in, bool reread) {
// nothing by default
}
@ -143,7 +143,7 @@ void SharedObject::writeExtraDelta(Bitstream& out, const SharedObject* reference
// nothing by default
}
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference) {
void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) {
// nothing by default
}

View file

@ -84,13 +84,15 @@ public:
virtual void writeExtra(Bitstream& out) const;
/// Reads the non-property contents of this object from the specified stream.
virtual void readExtra(Bitstream& in);
/// \param reread if true, reread the contents from the stream but don't reapply them
virtual void readExtra(Bitstream& in, bool reread = false);
/// Writes the delta-encoded non-property contents of this object to the specified stream.
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
/// Reads the delta-encoded non-property contents of this object from the specified stream.
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
/// \param reread if true, reread the contents from the stream but don't reapply them
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread = false);
/// Writes the subdivision of the contents of this object (preceeded by a
/// reference to the object itself) to the specified stream if necessary.

View file

@ -685,41 +685,17 @@ void HeightfieldHeightEditor::clear() {
}
static QByteArray encodeHeightfieldColor(int offsetX, int offsetY, int width, int height, const QByteArray& contents) {
QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE + contents.size(), 0);
QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0);
qint32* header = (qint32*)inflated.data();
*header++ = offsetX;
*header++ = offsetY;
*header++ = width;
*header++ = height;
if (!contents.isEmpty()) {
// encode with Paeth filter (see http://en.wikipedia.org/wiki/Portable_Network_Graphics#Filtering)
const uchar* src = (const uchar*)contents.constData();
uchar* dest = (uchar*)inflated.data() + HEIGHTFIELD_DATA_HEADER_SIZE;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
int stride = width * DataBlock::COLOR_BYTES;
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
*dest = *src - src[-DataBlock::COLOR_BYTES];
}
for (int y = 1; y < height; y++) {
*dest++ = *src - src[-stride];
src++;
*dest++ = *src - src[-stride];
src++;
*dest++ = *src - src[-stride];
src++;
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
int a = src[-DataBlock::COLOR_BYTES];
int b = src[-stride];
int c = src[-stride - DataBlock::COLOR_BYTES];
int p = a + b - c;
int ad = abs(a - p);
int bd = abs(b - p);
int cd = abs(c - p);
*dest = *src - (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c));
}
}
QBuffer buffer(&inflated);
buffer.open(QIODevice::WriteOnly | QIODevice::Append);
QImage((const uchar*)contents.constData(), width, height, width * DataBlock::COLOR_BYTES,
QImage::Format_RGB888).save(&buffer, "JPG");
}
return qCompress(inflated);
}
@ -731,35 +707,19 @@ static QByteArray decodeHeightfieldColor(const QByteArray& encoded, int& offsetX
offsetY = *header++;
width = *header++;
height = *header++;
QByteArray contents(inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE, 0);
if (!contents.isEmpty()) {
const uchar* src = (const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE;
uchar* dest = (uchar*)contents.data();
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
int stride = width * DataBlock::COLOR_BYTES;
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
*dest = *src + dest[-DataBlock::COLOR_BYTES];
}
for (int y = 1; y < height; y++) {
*dest = (*src++) + dest[-stride];
dest++;
*dest = (*src++) + dest[-stride];
dest++;
*dest = (*src++) + dest[-stride];
dest++;
for (uchar* end = dest + stride - DataBlock::COLOR_BYTES; dest != end; dest++, src++) {
int a = dest[-DataBlock::COLOR_BYTES];
int b = dest[-stride];
int c = dest[-stride - DataBlock::COLOR_BYTES];
int p = a + b - c;
int ad = abs(a - p);
int bd = abs(b - p);
int cd = abs(c - p);
*dest = *src + (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c));
}
}
int payloadSize = inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE;
if (payloadSize == 0) {
return QByteArray();
}
QImage image = QImage::fromData((const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE, payloadSize, "JPG");
if (image.format() != QImage::Format_RGB888) {
image = image.convertToFormat(QImage::Format_RGB888);
}
QByteArray contents(width * height * DataBlock::COLOR_BYTES, 0);
char* dest = contents.data();
int stride = width * DataBlock::COLOR_BYTES;
for (int y = 0; y < height; y++, dest += stride) {
memcpy(dest, image.constScanLine(y), stride);
}
return contents;
}
@ -3722,9 +3682,18 @@ void Heightfield::writeExtra(Bitstream& out) const {
_root->write(state);
}
void Heightfield::readExtra(Bitstream& in) {
void Heightfield::readExtra(Bitstream& in, bool reread) {
if (getWillBeVoxelized()) {
in >> _height >> _color >> _material >> _stack;
if (reread) {
HeightfieldHeightPointer height;
HeightfieldColorPointer color;
HeightfieldMaterialPointer material;
HeightfieldStackPointer stack;
in >> height >> color >> material >> stack;
} else {
in >> _height >> _color >> _material >> _stack;
}
return;
}
MetavoxelLOD lod;
@ -3736,7 +3705,9 @@ void Heightfield::readExtra(Bitstream& in) {
HeightfieldNodePointer root(new HeightfieldNode());
root->read(state);
setRoot(root);
if (!reread) {
setRoot(root);
}
}
void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const {
@ -3760,7 +3731,7 @@ void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference)
}
}
void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) {
void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) {
MetavoxelLOD lod, referenceLOD;
if (in.getContext()) {
MetavoxelStreamBase* base = static_cast<MetavoxelStreamBase*>(in.getContext());
@ -3770,16 +3741,21 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) {
HeightfieldStreamBase base = { in, lod, referenceLOD };
HeightfieldStreamState state = { base, glm::vec2(), 1.0f };
setRoot(static_cast<const Heightfield*>(reference)->getRoot());
bool changed;
in >> changed;
if (changed) {
HeightfieldNodePointer root(new HeightfieldNode());
root->readDelta(static_cast<const Heightfield*>(reference)->getRoot(), state);
setRoot(root);
if (!reread) {
setRoot(root);
}
} else if (state.becameSubdividedOrCollapsed()) {
setRoot(HeightfieldNodePointer(_root->readSubdivision(state)));
HeightfieldNodePointer root(_root->readSubdivision(state));
if (!reread) {
setRoot(root);
}
} else if (!reread) {
setRoot(static_cast<const Heightfield*>(reference)->getRoot());
}
}

View file

@ -820,9 +820,9 @@ public:
virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal);
virtual void writeExtra(Bitstream& out) const;
virtual void readExtra(Bitstream& in);
virtual void readExtra(Bitstream& in, bool reread);
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread);
virtual void maybeWriteSubdivision(Bitstream& out);
virtual SharedObject* readSubdivision(Bitstream& in);

View file

@ -158,7 +158,8 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart) {
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QMetaObject::invokeMethod(this, "invokedRequest",
Q_ARG(const QString&, path),
@ -166,13 +167,15 @@ void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessMan
Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QHttpMultiPart*, dataMultiPart));
Q_ARG(QHttpMultiPart*, dataMultiPart),
Q_ARG(QVariantMap, propertyMap));
}
void AccountManager::unauthenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart) {
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QMetaObject::invokeMethod(this, "invokedRequest",
Q_ARG(const QString&, path),
@ -180,14 +183,16 @@ void AccountManager::unauthenticatedRequest(const QString& path, QNetworkAccessM
Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QHttpMultiPart*, dataMultiPart));
Q_ARG(QHttpMultiPart*, dataMultiPart),
Q_ARG(QVariantMap, propertyMap));
}
void AccountManager::invokedRequest(const QString& path,
bool requiresAuthentication,
QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
@ -235,7 +240,9 @@ void AccountManager::invokedRequest(const QString& path,
} else {
networkReply = networkAccessManager.put(networkRequest, dataMultiPart);
}
dataMultiPart->setParent(networkReply);
// make sure dataMultiPart is destroyed when the reply is
connect(networkReply, &QNetworkReply::destroyed, dataMultiPart, &QHttpMultiPart::deleteLater);
} else {
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (operation == QNetworkAccessManager::PostOperation) {
@ -255,6 +262,14 @@ void AccountManager::invokedRequest(const QString& path,
}
if (networkReply) {
if (!propertyMap.isEmpty()) {
// we have properties to set on the reply so the user can check them after
foreach(const QString& propertyKey, propertyMap.keys()) {
networkReply->setProperty(qPrintable(propertyKey), propertyMap.value(propertyKey));
}
}
if (!callbackParams.isEmpty()) {
// if we have information for a callback, insert the callbackParams into our local map
_pendingCallbackMap.insert(networkReply, callbackParams);

View file

@ -48,13 +48,15 @@ public:
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray(),
QHttpMultiPart* dataMultiPart = NULL);
QHttpMultiPart* dataMultiPart = NULL,
const QVariantMap& propertyMap = QVariantMap());
void unauthenticatedRequest(const QString& path,
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray(),
QHttpMultiPart* dataMultiPart = NULL);
QHttpMultiPart* dataMultiPart = NULL,
const QVariantMap& propertyMap = QVariantMap()) ;
const QUrl& getAuthURL() const { return _authURL; }
void setAuthURL(const QUrl& authURL);
@ -109,7 +111,8 @@ private:
QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart);
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap);
QUrl _authURL;
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;

View file

@ -121,14 +121,16 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
if (!handleUsername(lookupUrl.authority())) {
// we're assuming this is either a network address or global place name
// check if it is a network address first
if (!handleNetworkAddress(lookupUrl.host()
if (handleNetworkAddress(lookupUrl.host()
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) {
// we may have a path that defines a relative viewpoint - if so we should jump to that now
handleRelativeViewpoint(lookupUrl.path());
} else {
// wasn't an address - lookup the place name
attemptPlaceNameLookup(lookupUrl.host());
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path());
}
// we may have a path that defines a relative viewpoint - if so we should jump to that now
handleRelativeViewpoint(lookupUrl.path());
}
return true;
@ -166,12 +168,14 @@ void AddressManager::handleAPIResponse(QNetworkReply& requestReply) {
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject dataObject = responseObject["data"].toObject();
goToAddressFromObject(dataObject.toVariantMap());
goToAddressFromObject(dataObject.toVariantMap(), requestReply);
emit lookupResultsFinished();
}
void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
const char OVERRIDE_PATH_KEY[] = "override_path";
void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const QNetworkReply& reply) {
const QString DATA_OBJECT_PLACE_KEY = "place";
const QString DATA_OBJECT_USER_LOCATION_KEY = "location";
@ -205,6 +209,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
qDebug() << "Possible domain change required to connect to" << domainHostname
<< "on" << DEFAULT_DOMAIN_SERVER_PORT;
emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT);
} else {
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
@ -213,6 +219,9 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
QUuid domainID(domainIDString);
qDebug() << "Possible domain change required to connect to domain with ID" << domainID
<< "via ice-server at" << iceServerAddress;
emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID);
}
@ -225,18 +234,29 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) {
QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString();
setRootPlaceName(newRootPlaceName);
// take the path that came back
const QString PLACE_PATH_KEY = "path";
QString returnedPath = locationMap[PLACE_PATH_KEY].toString();
// check if we had a path to override the path returned
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
bool shouldFaceViewpoint = locationMap.contains(LOCATION_API_ONLINE_KEY);
if (!returnedPath.isEmpty()) {
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) {
qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
if (!overridePath.isEmpty()) {
if (!handleRelativeViewpoint(overridePath)){
qDebug() << "User entered path could not be handled as a viewpoint - " << overridePath;
}
} else {
// take the path that came back
const QString PLACE_PATH_KEY = "path";
QString returnedPath = locationMap[PLACE_PATH_KEY].toString();
bool shouldFaceViewpoint = locationMap.contains(LOCATION_API_ONLINE_KEY);
if (!returnedPath.isEmpty()) {
// try to parse this returned path as a viewpoint, that's the only thing it could be for now
if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) {
qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath;
}
}
}
} else {
qDebug() << "Received an address manager API response with no domain key. Cannot parse.";
qDebug() << locationMap;
@ -262,12 +282,21 @@ void AddressManager::handleAPIError(QNetworkReply& errorReply) {
const QString GET_PLACE = "/api/v1/places/%1";
void AddressManager::attemptPlaceNameLookup(const QString& lookupString) {
void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath) {
// assume this is a place name and see if we can get any info on it
QString placeName = QUrl::toPercentEncoding(lookupString);
QVariantMap requestParams;
if (!overridePath.isEmpty()) {
requestParams.insert(OVERRIDE_PATH_KEY, overridePath);
}
AccountManager::getInstance().unauthenticatedRequest(GET_PLACE.arg(placeName),
QNetworkAccessManager::GetOperation,
apiCallbackParameters());
apiCallbackParameters(),
QByteArray(),
NULL,
requestParams);
}
bool AddressManager::handleNetworkAddress(const QString& lookupString) {

View file

@ -47,7 +47,7 @@ public:
const QString& getRootPlaceName() const { return _rootPlaceName; }
void setRootPlaceName(const QString& rootPlaceName);
void attemptPlaceNameLookup(const QString& lookupString);
void attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath = QString());
void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; }
void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
@ -57,7 +57,7 @@ public:
public slots:
void handleLookupString(const QString& lookupString);
void goToUser(const QString& username);
void goToAddressFromObject(const QVariantMap& addressMap);
void goToAddressFromObject(const QVariantMap& addressMap, const QNetworkReply& reply);
void storeCurrentAddress();

View file

@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeAudioStreamStats:
return 1;
case PacketTypeMetavoxelData:
return 11;
return 12;
default:
return 0;
}