mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 20:58:38 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into virtualEntities
This commit is contained in:
commit
e800d5457b
30 changed files with 502 additions and 338 deletions
|
@ -210,12 +210,11 @@ void Agent::run() {
|
||||||
|
|
||||||
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
|
QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
|
||||||
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
|
|
||||||
|
QNetworkDiskCache* cache = new QNetworkDiskCache();
|
||||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
|
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
|
||||||
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
|
networkAccessManager.setCache(cache);
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_ARG(QAbstractNetworkCache*, cache));
|
|
||||||
|
|
||||||
qDebug() << "Downloading script at" << scriptURL.toString();
|
qDebug() << "Downloading script at" << scriptURL.toString();
|
||||||
|
|
||||||
|
@ -270,4 +269,5 @@ void Agent::run() {
|
||||||
|
|
||||||
void Agent::aboutToFinish() {
|
void Agent::aboutToFinish() {
|
||||||
_scriptEngine.stop();
|
_scriptEngine.stop();
|
||||||
|
NetworkAccessManager::getInstance().clearAccessCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ AudioMixer::~AudioMixer() {
|
||||||
|
|
||||||
const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f;
|
const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f;
|
||||||
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
|
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
|
||||||
|
const float ATTENUATION_EPSILON_DISTANCE = 0.1f;
|
||||||
|
|
||||||
void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,
|
void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,
|
||||||
AvatarAudioRingBuffer* listeningNodeBuffer) {
|
AvatarAudioRingBuffer* listeningNodeBuffer) {
|
||||||
|
@ -107,7 +108,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
||||||
|
|
||||||
float distanceBetween = glm::length(relativePosition);
|
float distanceBetween = glm::length(relativePosition);
|
||||||
|
|
||||||
if (distanceBetween < EPSILON) {
|
if (distanceBetween < EPSILON) {
|
||||||
distanceBetween = EPSILON;
|
distanceBetween = EPSILON;
|
||||||
}
|
}
|
||||||
|
@ -124,6 +125,12 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition());
|
shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
|
||||||
|
attenuationCoefficient *= reinterpret_cast<InjectedAudioRingBuffer*>(bufferToAdd)->getAttenuationRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldAttenuate = shouldAttenuate && distanceBetween > ATTENUATION_EPSILON_DISTANCE;
|
||||||
|
|
||||||
if (shouldAttenuate) {
|
if (shouldAttenuate) {
|
||||||
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
||||||
|
|
||||||
|
@ -131,9 +138,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
float radius = 0.0f;
|
float radius = 0.0f;
|
||||||
|
|
||||||
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
|
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
|
||||||
InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd;
|
radius = reinterpret_cast<InjectedAudioRingBuffer*>(bufferToAdd)->getRadius();
|
||||||
radius = injectedBuffer->getRadius();
|
|
||||||
attenuationCoefficient *= injectedBuffer->getAttenuationRatio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radius == 0 || (distanceSquareToSource > radius * radius)) {
|
if (radius == 0 || (distanceSquareToSource > radius * radius)) {
|
||||||
|
@ -158,7 +163,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
|
const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
|
||||||
|
|
||||||
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
|
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
|
||||||
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
|
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
|
||||||
|
|
||||||
// multiply the current attenuation coefficient by the calculated off axis coefficient
|
// multiply the current attenuation coefficient by the calculated off axis coefficient
|
||||||
attenuationCoefficient *= offAxisCoefficient;
|
attenuationCoefficient *= offAxisCoefficient;
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
const int SEND_INTERVAL = 50;
|
const int SEND_INTERVAL = 50;
|
||||||
|
|
||||||
MetavoxelServer::MetavoxelServer(const QByteArray& packet) :
|
MetavoxelServer::MetavoxelServer(const QByteArray& packet) :
|
||||||
ThreadedAssignment(packet) {
|
ThreadedAssignment(packet),
|
||||||
|
_sendTimer(this) {
|
||||||
|
|
||||||
_sendTimer.setSingleShot(true);
|
_sendTimer.setSingleShot(true);
|
||||||
connect(&_sendTimer, SIGNAL(timeout()), SLOT(sendDeltas()));
|
connect(&_sendTimer, SIGNAL(timeout()), SLOT(sendDeltas()));
|
||||||
|
@ -91,24 +92,54 @@ void MetavoxelServer::sendDeltas() {
|
||||||
|
|
||||||
MetavoxelSession::MetavoxelSession(const SharedNodePointer& node, MetavoxelServer* server) :
|
MetavoxelSession::MetavoxelSession(const SharedNodePointer& node, MetavoxelServer* server) :
|
||||||
Endpoint(node, new PacketRecord(), NULL),
|
Endpoint(node, new PacketRecord(), NULL),
|
||||||
_server(server) {
|
_server(server),
|
||||||
|
_reliableDeltaChannel(NULL) {
|
||||||
|
|
||||||
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&)));
|
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&)));
|
||||||
connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&)),
|
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived()));
|
||||||
SLOT(handleMessage(const QVariant&)));
|
connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&, Bitstream&)),
|
||||||
|
SLOT(handleMessage(const QVariant&, Bitstream&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSession::update() {
|
void MetavoxelSession::update() {
|
||||||
// wait until we have a valid lod
|
// wait until we have a valid lod before sending
|
||||||
if (_lod.isValid()) {
|
if (!_lod.isValid()) {
|
||||||
Endpoint::update();
|
return;
|
||||||
}
|
}
|
||||||
}
|
// if we're sending a reliable delta, wait until it's acknowledged
|
||||||
|
if (_reliableDeltaChannel) {
|
||||||
void MetavoxelSession::writeUpdateMessage(Bitstream& out) {
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
||||||
|
_sequencer.endPacket();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
int start = _sequencer.getOutputStream().getUnderlying().device()->pos();
|
||||||
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
||||||
PacketRecord* sendRecord = getLastAcknowledgedSendRecord();
|
PacketRecord* sendRecord = getLastAcknowledgedSendRecord();
|
||||||
_server->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod);
|
_server->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod);
|
||||||
|
out.flush();
|
||||||
|
int end = _sequencer.getOutputStream().getUnderlying().device()->pos();
|
||||||
|
if (end > _sequencer.getMaxPacketSize()) {
|
||||||
|
// we need to send the delta on the reliable channel
|
||||||
|
_reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
|
_reliableDeltaChannel->startMessage();
|
||||||
|
_reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start);
|
||||||
|
_reliableDeltaChannel->endMessage();
|
||||||
|
|
||||||
|
_reliableDeltaWriteMappings = out.getAndResetWriteMappings();
|
||||||
|
_reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten();
|
||||||
|
_reliableDeltaData = _server->getData();
|
||||||
|
_reliableDeltaLOD = _lod;
|
||||||
|
|
||||||
|
// go back to the beginning with the current packet and note that there's a delta pending
|
||||||
|
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
||||||
|
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
||||||
|
_sequencer.endPacket();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_sequencer.endPacket();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) {
|
void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
@ -116,7 +147,8 @@ void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* MetavoxelSession::maybeCreateSendRecord() const {
|
PacketRecord* MetavoxelSession::maybeCreateSendRecord() const {
|
||||||
return new PacketRecord(_lod, _server->getData());
|
return _reliableDeltaChannel ? new PacketRecord(_reliableDeltaLOD, _reliableDeltaData) :
|
||||||
|
new PacketRecord(_lod, _server->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSession::handleMessage(const QVariant& message) {
|
void MetavoxelSession::handleMessage(const QVariant& message) {
|
||||||
|
@ -134,3 +166,13 @@ void MetavoxelSession::handleMessage(const QVariant& message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetavoxelSession::checkReliableDeltaReceived() {
|
||||||
|
if (!_reliableDeltaChannel || _reliableDeltaChannel->getOffset() < _reliableDeltaReceivedOffset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_sequencer.getOutputStream().persistWriteMappings(_reliableDeltaWriteMappings);
|
||||||
|
_reliableDeltaWriteMappings = Bitstream::WriteMappings();
|
||||||
|
_reliableDeltaData = MetavoxelData();
|
||||||
|
_reliableDeltaChannel = NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void writeUpdateMessage(Bitstream& out);
|
|
||||||
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
||||||
|
|
||||||
virtual PacketRecord* maybeCreateSendRecord() const;
|
virtual PacketRecord* maybeCreateSendRecord() const;
|
||||||
|
@ -71,12 +70,19 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void handleMessage(const QVariant& message);
|
void handleMessage(const QVariant& message);
|
||||||
|
void checkReliableDeltaReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MetavoxelServer* _server;
|
MetavoxelServer* _server;
|
||||||
|
|
||||||
MetavoxelLOD _lod;
|
MetavoxelLOD _lod;
|
||||||
|
|
||||||
|
ReliableChannel* _reliableDeltaChannel;
|
||||||
|
int _reliableDeltaReceivedOffset;
|
||||||
|
MetavoxelData _reliableDeltaData;
|
||||||
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
|
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelServer_h
|
#endif // hifi_MetavoxelServer_h
|
||||||
|
|
|
@ -57,7 +57,7 @@ var LocationMenu = function(opts) {
|
||||||
y: 0,
|
y: 0,
|
||||||
width: menuWidth + 10,
|
width: menuWidth + 10,
|
||||||
height: (menuHeight * (pageSize + 1)) + 10,
|
height: (menuHeight * (pageSize + 1)) + 10,
|
||||||
color: { red: 0, green: 0, blue: 0},
|
backgroundColor: { red: 0, green: 0, blue: 0},
|
||||||
topMargin: 4,
|
topMargin: 4,
|
||||||
leftMargin: 4,
|
leftMargin: 4,
|
||||||
text: "",
|
text: "",
|
||||||
|
@ -71,7 +71,7 @@ var LocationMenu = function(opts) {
|
||||||
y: 0,
|
y: 0,
|
||||||
width: menuWidth,
|
width: menuWidth,
|
||||||
height: menuHeight,
|
height: menuHeight,
|
||||||
color: inactiveColor,
|
backgroundColor: inactiveColor,
|
||||||
topMargin: margin,
|
topMargin: margin,
|
||||||
leftMargin: margin,
|
leftMargin: margin,
|
||||||
text: (i == 0) ? "Loading..." : "",
|
text: (i == 0) ? "Loading..." : "",
|
||||||
|
@ -85,7 +85,7 @@ var LocationMenu = function(opts) {
|
||||||
y: 0,
|
y: 0,
|
||||||
width: menuWidth / 2,
|
width: menuWidth / 2,
|
||||||
height: menuHeight,
|
height: menuHeight,
|
||||||
color: disabledColor,
|
backgroundColor: disabledColor,
|
||||||
topMargin: margin,
|
topMargin: margin,
|
||||||
leftMargin: margin,
|
leftMargin: margin,
|
||||||
text: "Previous",
|
text: "Previous",
|
||||||
|
@ -97,7 +97,7 @@ var LocationMenu = function(opts) {
|
||||||
y: 0,
|
y: 0,
|
||||||
width: menuWidth / 2,
|
width: menuWidth / 2,
|
||||||
height: menuHeight,
|
height: menuHeight,
|
||||||
color: disabledColor,
|
backgroundColor: disabledColor,
|
||||||
topMargin: margin,
|
topMargin: margin,
|
||||||
leftMargin: margin,
|
leftMargin: margin,
|
||||||
text: "Next",
|
text: "Next",
|
||||||
|
@ -175,10 +175,10 @@ var LocationMenu = function(opts) {
|
||||||
if (start + i < this.locations.length) {
|
if (start + i < this.locations.length) {
|
||||||
location = this.locations[start + i];
|
location = this.locations[start + i];
|
||||||
update.text = (start + i + 1) + ". " + location.username;
|
update.text = (start + i + 1) + ". " + location.username;
|
||||||
update.color = inactiveColor;
|
update.backgroundColor = inactiveColor;
|
||||||
} else {
|
} else {
|
||||||
update.text = "";
|
update.text = "";
|
||||||
update.color = disabledColor;
|
update.backgroundColor = disabledColor;
|
||||||
}
|
}
|
||||||
Overlays.editOverlay(this.menuItems[i].overlay, update);
|
Overlays.editOverlay(this.menuItems[i].overlay, update);
|
||||||
this.menuItems[i].location = location;
|
this.menuItems[i].location = location;
|
||||||
|
@ -187,8 +187,8 @@ var LocationMenu = function(opts) {
|
||||||
this.previousEnabled = pageNumber > 0;
|
this.previousEnabled = pageNumber > 0;
|
||||||
this.nextEnabled = pageNumber < (this.numPages - 1);
|
this.nextEnabled = pageNumber < (this.numPages - 1);
|
||||||
|
|
||||||
Overlays.editOverlay(this.previousButton, { color: this.previousEnabled ? prevNextColor : disabledColor});
|
Overlays.editOverlay(this.previousButton, { backgroundColor: this.previousEnabled ? prevNextColor : disabledColor});
|
||||||
Overlays.editOverlay(this.nextButton, { color: this.nextEnabled ? prevNextColor : disabledColor });
|
Overlays.editOverlay(this.nextButton, { backgroundColor: this.nextEnabled ? prevNextColor : disabledColor });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mousePressEvent = function(event) {
|
this.mousePressEvent = function(event) {
|
||||||
|
@ -198,17 +198,17 @@ var LocationMenu = function(opts) {
|
||||||
self.toggleMenu();
|
self.toggleMenu();
|
||||||
} else if (clickedOverlay == self.previousButton) {
|
} else if (clickedOverlay == self.previousButton) {
|
||||||
if (self.previousEnabled) {
|
if (self.previousEnabled) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: activeColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
|
||||||
}
|
}
|
||||||
} else if (clickedOverlay == self.nextButton) {
|
} else if (clickedOverlay == self.nextButton) {
|
||||||
if (self.nextEnabled) {
|
if (self.nextEnabled) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: activeColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0; i < self.menuItems.length; i++) {
|
for (var i = 0; i < self.menuItems.length; i++) {
|
||||||
if (clickedOverlay == self.menuItems[i].overlay) {
|
if (clickedOverlay == self.menuItems[i].overlay) {
|
||||||
if (self.menuItems[i].location != null) {
|
if (self.menuItems[i].location != null) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: activeColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -221,19 +221,19 @@ var LocationMenu = function(opts) {
|
||||||
|
|
||||||
if (clickedOverlay == self.previousButton) {
|
if (clickedOverlay == self.previousButton) {
|
||||||
if (self.previousEnabled) {
|
if (self.previousEnabled) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
|
||||||
self.goToPage(self.page - 1);
|
self.goToPage(self.page - 1);
|
||||||
}
|
}
|
||||||
} else if (clickedOverlay == self.nextButton) {
|
} else if (clickedOverlay == self.nextButton) {
|
||||||
if (self.nextEnabled) {
|
if (self.nextEnabled) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
|
||||||
self.goToPage(self.page + 1);
|
self.goToPage(self.page + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0; i < self.menuItems.length; i++) {
|
for (var i = 0; i < self.menuItems.length; i++) {
|
||||||
if (clickedOverlay == self.menuItems[i].overlay) {
|
if (clickedOverlay == self.menuItems[i].overlay) {
|
||||||
if (self.menuItems[i].location != null) {
|
if (self.menuItems[i].location != null) {
|
||||||
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
|
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
|
||||||
var location = self.menuItems[i].location;
|
var location = self.menuItems[i].location;
|
||||||
Window.location = "hifi://" + location.domain + "/"
|
Window.location = "hifi://" + location.domain + "/"
|
||||||
+ location.x + "," + location.y + "," + location.z;
|
+ location.x + "," + location.y + "," + location.z;
|
||||||
|
|
Binary file not shown.
|
@ -316,11 +316,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
|
|
||||||
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
|
QNetworkDiskCache* cache = new QNetworkDiskCache();
|
||||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
|
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
|
||||||
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
|
networkAccessManager.setCache(cache);
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_ARG(QAbstractNetworkCache*, cache));
|
|
||||||
|
|
||||||
ResourceCache::setRequestLimit(3);
|
ResourceCache::setRequestLimit(3);
|
||||||
|
|
||||||
|
|
|
@ -1006,7 +1006,6 @@ void Menu::goToDomainDialog() {
|
||||||
domainDialog.setWindowTitle("Go to Domain");
|
domainDialog.setWindowTitle("Go to Domain");
|
||||||
domainDialog.setLabelText("Domain server:");
|
domainDialog.setLabelText("Domain server:");
|
||||||
domainDialog.setTextValue(currentDomainHostname);
|
domainDialog.setTextValue(currentDomainHostname);
|
||||||
domainDialog.setWindowFlags(Qt::Sheet);
|
|
||||||
domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height());
|
domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height());
|
||||||
|
|
||||||
int dialogReturn = domainDialog.exec();
|
int dialogReturn = domainDialog.exec();
|
||||||
|
@ -1044,7 +1043,6 @@ void Menu::goTo() {
|
||||||
QString destination = QString();
|
QString destination = QString();
|
||||||
|
|
||||||
gotoDialog.setTextValue(destination);
|
gotoDialog.setTextValue(destination);
|
||||||
gotoDialog.setWindowFlags(Qt::Sheet);
|
|
||||||
gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height());
|
gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height());
|
||||||
|
|
||||||
int dialogReturn = gotoDialog.exec();
|
int dialogReturn = gotoDialog.exec();
|
||||||
|
@ -1160,7 +1158,6 @@ void Menu::goToLocation() {
|
||||||
coordinateDialog.setWindowTitle("Go to Location");
|
coordinateDialog.setWindowTitle("Go to Location");
|
||||||
coordinateDialog.setLabelText("Coordinate as x,y,z:");
|
coordinateDialog.setLabelText("Coordinate as x,y,z:");
|
||||||
coordinateDialog.setTextValue(currentLocation);
|
coordinateDialog.setTextValue(currentLocation);
|
||||||
coordinateDialog.setWindowFlags(Qt::Sheet);
|
|
||||||
coordinateDialog.resize(coordinateDialog.parentWidget()->size().width() * 0.30, coordinateDialog.size().height());
|
coordinateDialog.resize(coordinateDialog.parentWidget()->size().width() * 0.30, coordinateDialog.size().height());
|
||||||
|
|
||||||
int dialogReturn = coordinateDialog.exec();
|
int dialogReturn = coordinateDialog.exec();
|
||||||
|
@ -1225,7 +1222,6 @@ void Menu::nameLocation() {
|
||||||
"(wherever you are standing and looking now) as you.\n\n"
|
"(wherever you are standing and looking now) as you.\n\n"
|
||||||
"Location name:");
|
"Location name:");
|
||||||
|
|
||||||
nameDialog.setWindowFlags(Qt::Sheet);
|
|
||||||
nameDialog.resize((int) (nameDialog.parentWidget()->size().width() * 0.30), nameDialog.size().height());
|
nameDialog.resize((int) (nameDialog.parentWidget()->size().width() * 0.30), nameDialog.size().height());
|
||||||
|
|
||||||
if (nameDialog.exec() == QDialog::Accepted) {
|
if (nameDialog.exec() == QDialog::Accepted) {
|
||||||
|
|
|
@ -13,14 +13,13 @@
|
||||||
|
|
||||||
#include "MIDIManager.h"
|
#include "MIDIManager.h"
|
||||||
|
|
||||||
#ifdef HAVE_RTMIDI
|
|
||||||
|
|
||||||
MIDIManager& MIDIManager::getInstance() {
|
MIDIManager& MIDIManager::getInstance() {
|
||||||
static MIDIManager sharedInstance;
|
static MIDIManager sharedInstance;
|
||||||
return sharedInstance;
|
return sharedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* message, void* userData) {
|
void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* message, void* userData) {
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
|
|
||||||
MIDIEvent callbackEvent;
|
MIDIEvent callbackEvent;
|
||||||
callbackEvent.deltaTime = deltaTime;
|
callbackEvent.deltaTime = deltaTime;
|
||||||
|
@ -36,15 +35,19 @@ void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* mes
|
||||||
}
|
}
|
||||||
|
|
||||||
emit getInstance().midiEvent(callbackEvent);
|
emit getInstance().midiEvent(callbackEvent);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIManager::~MIDIManager() {
|
MIDIManager::~MIDIManager() {
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
delete _midiInput;
|
delete _midiInput;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const int DEFAULT_MIDI_PORT = 0;
|
const int DEFAULT_MIDI_PORT = 0;
|
||||||
|
|
||||||
void MIDIManager::openDefaultPort() {
|
void MIDIManager::openDefaultPort() {
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
if (!_midiInput) {
|
if (!_midiInput) {
|
||||||
_midiInput = new RtMidiIn();
|
_midiInput = new RtMidiIn();
|
||||||
|
|
||||||
|
@ -63,6 +66,5 @@ void MIDIManager::openDefaultPort() {
|
||||||
_midiInput = NULL;
|
_midiInput = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
}
|
||||||
#endif
|
|
|
@ -12,14 +12,14 @@
|
||||||
#ifndef hifi_MIDIManager_h
|
#ifndef hifi_MIDIManager_h
|
||||||
#define hifi_MIDIManager_h
|
#define hifi_MIDIManager_h
|
||||||
|
|
||||||
#ifdef HAVE_RTMIDI
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
#include <MIDIEvent.h>
|
#include <MIDIEvent.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
#include <RtMidi.h>
|
#include <RtMidi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class MIDIManager : public QObject {
|
class MIDIManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -36,7 +36,9 @@ public:
|
||||||
~MIDIManager();
|
~MIDIManager();
|
||||||
|
|
||||||
void openDefaultPort();
|
void openDefaultPort();
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
bool hasDevice() const { return !!_midiInput; }
|
bool hasDevice() const { return !!_midiInput; }
|
||||||
|
#endif
|
||||||
public slots:
|
public slots:
|
||||||
unsigned int NoteOn() const { return 144; }
|
unsigned int NoteOn() const { return 144; }
|
||||||
unsigned int NoteOff() const { return 128; }
|
unsigned int NoteOff() const { return 128; }
|
||||||
|
@ -46,10 +48,10 @@ signals:
|
||||||
void midiEvent(const MIDIEvent& event);
|
void midiEvent(const MIDIEvent& event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifdef HAVE_RTMIDI
|
||||||
RtMidiIn* _midiInput;
|
RtMidiIn* _midiInput;
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_MIDIManager_h
|
#endif // hifi_MIDIManager_h
|
||||||
|
|
|
@ -71,6 +71,16 @@ void SixenseManager::setFilter(bool filter) {
|
||||||
|
|
||||||
void SixenseManager::update(float deltaTime) {
|
void SixenseManager::update(float deltaTime) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
// if the controllers haven't been moved in a while, disable
|
||||||
|
const unsigned int MOVEMENT_DISABLE_SECONDS = 3;
|
||||||
|
if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) {
|
||||||
|
Hand* hand = Application::getInstance()->getAvatar()->getHand();
|
||||||
|
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
|
||||||
|
it->setActive(false);
|
||||||
|
}
|
||||||
|
_lastMovement = usecTimestampNow();
|
||||||
|
}
|
||||||
|
|
||||||
if (sixenseGetNumActiveControllers() == 0) {
|
if (sixenseGetNumActiveControllers() == 0) {
|
||||||
_hydrasConnected = false;
|
_hydrasConnected = false;
|
||||||
return;
|
return;
|
||||||
|
@ -154,6 +164,11 @@ void SixenseManager::update(float deltaTime) {
|
||||||
// no latency.
|
// no latency.
|
||||||
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
||||||
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
|
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
|
||||||
|
|
||||||
|
// adjustment for hydra controllers fit into hands
|
||||||
|
float sign = (i == 0) ? -1.0f : 1.0f;
|
||||||
|
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
|
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
|
||||||
|
|
||||||
// use the velocity to determine whether there's any movement (if the hand isn't new)
|
// use the velocity to determine whether there's any movement (if the hand isn't new)
|
||||||
|
@ -180,14 +195,6 @@ void SixenseManager::update(float deltaTime) {
|
||||||
if (numActiveControllers == 2) {
|
if (numActiveControllers == 2) {
|
||||||
updateCalibration(controllers);
|
updateCalibration(controllers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the controllers haven't been moved in a while, disable
|
|
||||||
const unsigned int MOVEMENT_DISABLE_SECONDS = 3;
|
|
||||||
if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) {
|
|
||||||
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
|
|
||||||
it->setActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // HAVE_SIXENSE
|
#endif // HAVE_SIXENSE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
Overlay::Overlay() :
|
Overlay::Overlay() :
|
||||||
_parent(NULL),
|
_parent(NULL),
|
||||||
_alpha(DEFAULT_ALPHA),
|
_alpha(DEFAULT_ALPHA),
|
||||||
_color(DEFAULT_BACKGROUND_COLOR),
|
_color(DEFAULT_OVERLAY_COLOR),
|
||||||
_visible(true),
|
_visible(true),
|
||||||
_anchor(NO_ANCHOR)
|
_anchor(NO_ANCHOR)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include <SharedUtil.h> // for xColor
|
#include <SharedUtil.h> // for xColor
|
||||||
|
|
||||||
const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 };
|
const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||||
const float DEFAULT_ALPHA = 0.7f;
|
const float DEFAULT_ALPHA = 0.7f;
|
||||||
|
|
||||||
class Overlay : public QObject {
|
class Overlay : public QObject {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
|
|
||||||
TextOverlay::TextOverlay() :
|
TextOverlay::TextOverlay() :
|
||||||
|
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
|
||||||
_leftMargin(DEFAULT_MARGIN),
|
_leftMargin(DEFAULT_MARGIN),
|
||||||
_topMargin(DEFAULT_MARGIN),
|
_topMargin(DEFAULT_MARGIN),
|
||||||
_fontSize(DEFAULT_FONTSIZE)
|
_fontSize(DEFAULT_FONTSIZE)
|
||||||
|
@ -33,7 +34,7 @@ void TextOverlay::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const float MAX_COLOR = 255;
|
const float MAX_COLOR = 255;
|
||||||
glColor4f(0 / MAX_COLOR, 0 / MAX_COLOR, 0 / MAX_COLOR, _alpha);
|
glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha);
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glVertex2f(_bounds.left(), _bounds.top());
|
glVertex2f(_bounds.left(), _bounds.top());
|
||||||
|
@ -82,6 +83,18 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
|
||||||
setText(text.toVariant().toString());
|
setText(text.toVariant().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue backgroundColor = properties.property("backgroundColor");
|
||||||
|
if (backgroundColor.isValid()) {
|
||||||
|
QScriptValue red = backgroundColor.property("red");
|
||||||
|
QScriptValue green = backgroundColor.property("green");
|
||||||
|
QScriptValue blue = backgroundColor.property("blue");
|
||||||
|
if (red.isValid() && green.isValid() && blue.isValid()) {
|
||||||
|
_backgroundColor.red = red.toVariant().toInt();
|
||||||
|
_backgroundColor.green = green.toVariant().toInt();
|
||||||
|
_backgroundColor.blue = blue.toVariant().toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.property("leftMargin").isValid()) {
|
if (properties.property("leftMargin").isValid()) {
|
||||||
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
|
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Overlay.h"
|
#include "Overlay.h"
|
||||||
#include "Overlay2D.h"
|
#include "Overlay2D.h"
|
||||||
|
|
||||||
|
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
|
||||||
const int DEFAULT_MARGIN = 10;
|
const int DEFAULT_MARGIN = 10;
|
||||||
const int DEFAULT_FONTSIZE = 11;
|
const int DEFAULT_FONTSIZE = 11;
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
|
xColor _backgroundColor;
|
||||||
int _leftMargin;
|
int _leftMargin;
|
||||||
int _topMargin;
|
int _topMargin;
|
||||||
int _fontSize;
|
int _fontSize;
|
||||||
|
|
|
@ -497,17 +497,7 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
|
_memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);
|
||||||
|
|
||||||
// create our simple fragment shader if we're the first system to init
|
// create our simple fragment shader if we're the first system to init
|
||||||
if (!_perlinModulateProgram.isLinked()) {
|
if (!_shadowMapProgram.isLinked()) {
|
||||||
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath()
|
|
||||||
+ "shaders/perlin_modulate.vert");
|
|
||||||
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath()
|
|
||||||
+ "shaders/perlin_modulate.frag");
|
|
||||||
_perlinModulateProgram.link();
|
|
||||||
|
|
||||||
_perlinModulateProgram.bind();
|
|
||||||
_perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
|
|
||||||
_perlinModulateProgram.release();
|
|
||||||
|
|
||||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
Application::resourcesPath() + "shaders/shadow_map.vert");
|
Application::resourcesPath() + "shaders/shadow_map.vert");
|
||||||
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
@ -1468,7 +1458,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) {
|
||||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
|
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
|
||||||
|
|
||||||
} else if (texture) {
|
} else if (texture) {
|
||||||
_perlinModulateProgram.bind();
|
bindPerlinModulateProgram();
|
||||||
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID());
|
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2118,6 +2108,22 @@ unsigned long VoxelSystem::getVoxelMemoryUsageGPU() {
|
||||||
return (_initialMemoryUsageGPU - currentFreeMemory);
|
return (_initialMemoryUsageGPU - currentFreeMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::bindPerlinModulateProgram() {
|
||||||
|
if (!_perlinModulateProgram.isLinked()) {
|
||||||
|
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
|
Application::resourcesPath() + "shaders/perlin_modulate.vert");
|
||||||
|
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
Application::resourcesPath() + "shaders/perlin_modulate.frag");
|
||||||
|
_perlinModulateProgram.link();
|
||||||
|
|
||||||
|
_perlinModulateProgram.bind();
|
||||||
|
_perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_perlinModulateProgram.bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Swizzle value of bit pairs of the value of index
|
// Swizzle value of bit pairs of the value of index
|
||||||
unsigned short VoxelSystem::_sSwizzledOcclusionBits[64] = {
|
unsigned short VoxelSystem::_sSwizzledOcclusionBits[64] = {
|
||||||
0x0000, // 00000000
|
0x0000, // 00000000
|
||||||
|
|
|
@ -233,6 +233,8 @@ private:
|
||||||
static ProgramObject _cascadedShadowMapProgram;
|
static ProgramObject _cascadedShadowMapProgram;
|
||||||
static int _shadowDistancesLocation;
|
static int _shadowDistancesLocation;
|
||||||
|
|
||||||
|
static void bindPerlinModulateProgram();
|
||||||
|
|
||||||
int _hookID;
|
int _hookID;
|
||||||
std::vector<glBufferIndex> _freeIndexes;
|
std::vector<glBufferIndex> _freeIndexes;
|
||||||
QMutex _freeIndexLock;
|
QMutex _freeIndexLock;
|
||||||
|
|
|
@ -274,6 +274,26 @@ void Bitstream::persistAndResetReadMappings() {
|
||||||
persistReadMappings(getAndResetReadMappings());
|
persistReadMappings(getAndResetReadMappings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitstream::copyPersistentMappings(const Bitstream& other) {
|
||||||
|
_objectStreamerStreamer.copyPersistentMappings(other._objectStreamerStreamer);
|
||||||
|
_typeStreamerStreamer.copyPersistentMappings(other._typeStreamerStreamer);
|
||||||
|
_attributeStreamer.copyPersistentMappings(other._attributeStreamer);
|
||||||
|
_scriptStringStreamer.copyPersistentMappings(other._scriptStringStreamer);
|
||||||
|
_sharedObjectStreamer.copyPersistentMappings(other._sharedObjectStreamer);
|
||||||
|
_sharedObjectReferences = other._sharedObjectReferences;
|
||||||
|
_weakSharedObjectHash = other._weakSharedObjectHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bitstream::clearPersistentMappings() {
|
||||||
|
_objectStreamerStreamer.clearPersistentMappings();
|
||||||
|
_typeStreamerStreamer.clearPersistentMappings();
|
||||||
|
_attributeStreamer.clearPersistentMappings();
|
||||||
|
_scriptStringStreamer.clearPersistentMappings();
|
||||||
|
_sharedObjectStreamer.clearPersistentMappings();
|
||||||
|
_sharedObjectReferences.clear();
|
||||||
|
_weakSharedObjectHash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Bitstream::clearSharedObject(int id) {
|
void Bitstream::clearSharedObject(int id) {
|
||||||
SharedObjectPointer object = _sharedObjectStreamer.takePersistentValue(id);
|
SharedObjectPointer object = _sharedObjectStreamer.takePersistentValue(id);
|
||||||
if (object) {
|
if (object) {
|
||||||
|
@ -1122,7 +1142,7 @@ Bitstream& Bitstream::operator>(ObjectStreamerPointer& streamer) {
|
||||||
}
|
}
|
||||||
if (_metadataType == NO_METADATA) {
|
if (_metadataType == NO_METADATA) {
|
||||||
if (!metaObject) {
|
if (!metaObject) {
|
||||||
qWarning() << "Unknown class name:" << className;
|
throw BitstreamException(QString("Unknown class name: ") + className);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1252,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
||||||
}
|
}
|
||||||
if (_metadataType == NO_METADATA) {
|
if (_metadataType == NO_METADATA) {
|
||||||
if (!baseStreamer) {
|
if (!baseStreamer) {
|
||||||
qWarning() << "Unknown type name:" << typeName;
|
throw BitstreamException(QString("Unknown type name: ") + typeName);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1240,7 +1260,7 @@ Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) {
|
||||||
*this >> category;
|
*this >> category;
|
||||||
if (category == TypeStreamer::SIMPLE_CATEGORY) {
|
if (category == TypeStreamer::SIMPLE_CATEGORY) {
|
||||||
if (!streamer) {
|
if (!streamer) {
|
||||||
qWarning() << "Unknown type name:" << typeName;
|
throw BitstreamException(QString("Unknown type name: ") + typeName);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1441,7 +1461,7 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
_objectStreamerStreamer >> objectStreamer;
|
_objectStreamerStreamer >> objectStreamer;
|
||||||
if (delta) {
|
if (delta) {
|
||||||
if (!reference) {
|
if (!reference) {
|
||||||
qWarning() << "Delta without reference" << id << originID;
|
throw BitstreamException(QString("Delta without reference [id=%1, originID=%2]").arg(id).arg(originID));
|
||||||
}
|
}
|
||||||
objectStreamer->readRawDelta(*this, reference.data(), pointer.data());
|
objectStreamer->readRawDelta(*this, reference.data(), pointer.data());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1451,7 +1471,7 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
||||||
QObject* rawObject;
|
QObject* rawObject;
|
||||||
if (delta) {
|
if (delta) {
|
||||||
if (!reference) {
|
if (!reference) {
|
||||||
qWarning() << "Delta without reference" << id << originID;
|
throw BitstreamException(QString("Delta without reference [id=%1, originID=%2]").arg(id).arg(originID));
|
||||||
}
|
}
|
||||||
readRawDelta(rawObject, (const QObject*)reference.data());
|
readRawDelta(rawObject, (const QObject*)reference.data());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1682,6 +1702,10 @@ const TypeStreamer* Bitstream::createInvalidTypeStreamer() {
|
||||||
return streamer;
|
return streamer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitstreamException::BitstreamException(const QString& description) :
|
||||||
|
_description(description) {
|
||||||
|
}
|
||||||
|
|
||||||
QJsonValue JSONWriter::getData(bool value) {
|
QJsonValue JSONWriter::getData(bool value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,9 @@ public:
|
||||||
|
|
||||||
V takePersistentValue(int id) { V value = _persistentValues.take(id); _valueIDs.remove(value); return value; }
|
V takePersistentValue(int id) { V value = _persistentValues.take(id); _valueIDs.remove(value); return value; }
|
||||||
|
|
||||||
|
void copyPersistentMappings(const RepeatedValueStreamer& other);
|
||||||
|
void clearPersistentMappings();
|
||||||
|
|
||||||
RepeatedValueStreamer& operator<<(K value);
|
RepeatedValueStreamer& operator<<(K value);
|
||||||
RepeatedValueStreamer& operator>>(V& value);
|
RepeatedValueStreamer& operator>>(V& value);
|
||||||
|
|
||||||
|
@ -199,6 +202,29 @@ template<class K, class P, class V> inline RepeatedValueStreamer<K, P, V>&
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class K, class P, class V> inline void RepeatedValueStreamer<K, P, V>::copyPersistentMappings(
|
||||||
|
const RepeatedValueStreamer<K, P, V>& other) {
|
||||||
|
_lastPersistentID = other._lastPersistentID;
|
||||||
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
|
_persistentIDs = other._persistentIDs;
|
||||||
|
_transientOffsets.clear();
|
||||||
|
_lastTransientOffset = 0;
|
||||||
|
_persistentValues = other._persistentValues;
|
||||||
|
_transientValues.clear();
|
||||||
|
_valueIDs = other._valueIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class K, class P, class V> inline void RepeatedValueStreamer<K, P, V>::clearPersistentMappings() {
|
||||||
|
_lastPersistentID = 0;
|
||||||
|
_idStreamer.setBitsFromValue(_lastPersistentID);
|
||||||
|
_persistentIDs.clear();
|
||||||
|
_transientOffsets.clear();
|
||||||
|
_lastTransientOffset = 0;
|
||||||
|
_persistentValues.clear();
|
||||||
|
_transientValues.clear();
|
||||||
|
_valueIDs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// A stream for bit-aligned data. Through a combination of code generation, reflection, macros, and templates, provides a
|
/// A stream for bit-aligned data. Through a combination of code generation, reflection, macros, and templates, provides a
|
||||||
/// serialization mechanism that may be used for both networking and persistent storage. For unreliable networking, the
|
/// serialization mechanism that may be used for both networking and persistent storage. For unreliable networking, the
|
||||||
/// class provides a mapping system that resends mappings for ids until they are acknowledged (and thus persisted). For
|
/// class provides a mapping system that resends mappings for ids until they are acknowledged (and thus persisted). For
|
||||||
|
@ -303,6 +329,9 @@ public:
|
||||||
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA,
|
Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA,
|
||||||
GenericsMode = NO_GENERICS, QObject* parent = NULL);
|
GenericsMode = NO_GENERICS, QObject* parent = NULL);
|
||||||
|
|
||||||
|
/// Returns a reference to the underlying data stream.
|
||||||
|
QDataStream& getUnderlying() { return _underlying; }
|
||||||
|
|
||||||
/// Substitutes the supplied metaobject for the given class name's default mapping. This is mostly useful for testing the
|
/// Substitutes the supplied metaobject for the given class name's default mapping. This is mostly useful for testing the
|
||||||
/// process of mapping between different types, but may in the future be used for permanently renaming classes.
|
/// process of mapping between different types, but may in the future be used for permanently renaming classes.
|
||||||
void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject);
|
void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject);
|
||||||
|
@ -347,6 +376,12 @@ public:
|
||||||
/// Immediately persists and resets the read mappings.
|
/// Immediately persists and resets the read mappings.
|
||||||
void persistAndResetReadMappings();
|
void persistAndResetReadMappings();
|
||||||
|
|
||||||
|
/// Copies the persistent mappings from the specified other stream.
|
||||||
|
void copyPersistentMappings(const Bitstream& other);
|
||||||
|
|
||||||
|
/// Clears the persistent mappings for this stream.
|
||||||
|
void clearPersistentMappings();
|
||||||
|
|
||||||
/// Returns a reference to the weak hash storing shared objects for this stream.
|
/// Returns a reference to the weak hash storing shared objects for this stream.
|
||||||
const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _weakSharedObjectHash; }
|
const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _weakSharedObjectHash; }
|
||||||
|
|
||||||
|
@ -823,6 +858,19 @@ template<class K, class V> inline Bitstream& Bitstream::operator>>(QHash<K, V>&
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Thrown for unrecoverable errors.
|
||||||
|
class BitstreamException {
|
||||||
|
public:
|
||||||
|
|
||||||
|
BitstreamException(const QString& description);
|
||||||
|
|
||||||
|
const QString& getDescription() const { return _description; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString _description;
|
||||||
|
};
|
||||||
|
|
||||||
/// Provides a means of writing Bitstream-able data to JSON rather than the usual binary format in a manner that allows it to
|
/// Provides a means of writing Bitstream-able data to JSON rather than the usual binary format in a manner that allows it to
|
||||||
/// be manipulated and re-read, converted to binary, etc. To use, create a JSONWriter, stream values in using the << operator,
|
/// be manipulated and re-read, converted to binary, etc. To use, create a JSONWriter, stream values in using the << operator,
|
||||||
/// and call getDocument to obtain the JSON data.
|
/// and call getDocument to obtain the JSON data.
|
||||||
|
|
|
@ -113,17 +113,16 @@ Bitstream& DatagramSequencer::startPacket() {
|
||||||
_outgoingPacketStream << (quint32)record.packetNumber;
|
_outgoingPacketStream << (quint32)record.packetNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the high-priority messages
|
|
||||||
_outgoingPacketStream << (quint32)_highPriorityMessages.size();
|
|
||||||
foreach (const HighPriorityMessage& message, _highPriorityMessages) {
|
|
||||||
_outputStream << message.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the stream, allowing the caller to write the rest
|
// return the stream, allowing the caller to write the rest
|
||||||
return _outputStream;
|
return _outputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramSequencer::endPacket() {
|
void DatagramSequencer::endPacket() {
|
||||||
|
// write the high-priority messages
|
||||||
|
_outputStream << _highPriorityMessages.size();
|
||||||
|
foreach (const HighPriorityMessage& message, _highPriorityMessages) {
|
||||||
|
_outputStream << message.data;
|
||||||
|
}
|
||||||
_outputStream.flush();
|
_outputStream.flush();
|
||||||
|
|
||||||
// if we have space remaining, send some data from our reliable channels
|
// if we have space remaining, send some data from our reliable channels
|
||||||
|
@ -222,22 +221,22 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) {
|
||||||
_sendRecords.erase(_sendRecords.begin(), it + 1);
|
_sendRecords.erase(_sendRecords.begin(), it + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alert external parties so that they can read the middle
|
||||||
|
emit readyToRead(_inputStream);
|
||||||
|
|
||||||
// read and dispatch the high-priority messages
|
// read and dispatch the high-priority messages
|
||||||
quint32 highPriorityMessageCount;
|
int highPriorityMessageCount;
|
||||||
_incomingPacketStream >> highPriorityMessageCount;
|
_inputStream >> highPriorityMessageCount;
|
||||||
int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages;
|
int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages;
|
||||||
for (quint32 i = 0; i < highPriorityMessageCount; i++) {
|
for (int i = 0; i < highPriorityMessageCount; i++) {
|
||||||
QVariant data;
|
QVariant data;
|
||||||
_inputStream >> data;
|
_inputStream >> data;
|
||||||
if ((int)i >= _receivedHighPriorityMessages) {
|
if (i >= _receivedHighPriorityMessages) {
|
||||||
emit receivedHighPriorityMessage(data);
|
emit receivedHighPriorityMessage(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_receivedHighPriorityMessages = highPriorityMessageCount;
|
_receivedHighPriorityMessages = highPriorityMessageCount;
|
||||||
|
|
||||||
// alert external parties so that they can read the middle
|
|
||||||
emit readyToRead(_inputStream);
|
|
||||||
|
|
||||||
// read the reliable data, if any
|
// read the reliable data, if any
|
||||||
quint32 reliableChannels;
|
quint32 reliableChannels;
|
||||||
_incomingPacketStream >> reliableChannels;
|
_incomingPacketStream >> reliableChannels;
|
||||||
|
@ -253,6 +252,8 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) {
|
||||||
// record the receipt
|
// record the receipt
|
||||||
ReceiveRecord record = { _incomingPacketNumber, _inputStream.getAndResetReadMappings(), newHighPriorityMessages };
|
ReceiveRecord record = { _incomingPacketNumber, _inputStream.getAndResetReadMappings(), newHighPriorityMessages };
|
||||||
_receiveRecords.append(record);
|
_receiveRecords.append(record);
|
||||||
|
|
||||||
|
emit receiveRecorded();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramSequencer::sendClearSharedObjectMessage(int id) {
|
void DatagramSequencer::sendClearSharedObjectMessage(int id) {
|
||||||
|
@ -274,6 +275,11 @@ void DatagramSequencer::handleHighPriorityMessage(const QVariant& data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatagramSequencer::clearReliableChannel(QObject* object) {
|
||||||
|
ReliableChannel* channel = static_cast<ReliableChannel*>(object);
|
||||||
|
(channel->isOutput() ? _reliableOutputChannels : _reliableInputChannels).remove(channel->getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) {
|
void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) {
|
||||||
// stop acknowledging the recorded packets
|
// stop acknowledging the recorded packets
|
||||||
while (!_receiveRecords.isEmpty() && _receiveRecords.first().packetNumber <= record.lastReceivedPacketNumber) {
|
while (!_receiveRecords.isEmpty() && _receiveRecords.first().packetNumber <= record.lastReceivedPacketNumber) {
|
||||||
|
@ -295,7 +301,10 @@ void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) {
|
||||||
|
|
||||||
// acknowledge the received spans
|
// acknowledge the received spans
|
||||||
foreach (const ChannelSpan& span, record.spans) {
|
foreach (const ChannelSpan& span, record.spans) {
|
||||||
getReliableOutputChannel(span.channel)->spanAcknowledged(span);
|
ReliableChannel* channel = _reliableOutputChannels.value(span.channel);
|
||||||
|
if (channel) {
|
||||||
|
channel->spanAcknowledged(span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase the packet rate with every ack until we pass the slow start threshold; then, every round trip
|
// increase the packet rate with every ack until we pass the slow start threshold; then, every round trip
|
||||||
|
@ -310,7 +319,10 @@ void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) {
|
||||||
void DatagramSequencer::sendRecordLost(const SendRecord& record) {
|
void DatagramSequencer::sendRecordLost(const SendRecord& record) {
|
||||||
// notify the channels of their lost spans
|
// notify the channels of their lost spans
|
||||||
foreach (const ChannelSpan& span, record.spans) {
|
foreach (const ChannelSpan& span, record.spans) {
|
||||||
getReliableOutputChannel(span.channel)->spanLost(record.packetNumber, _outgoingPacketNumber + 1);
|
ReliableChannel* channel = _reliableOutputChannels.value(span.channel);
|
||||||
|
if (channel) {
|
||||||
|
channel->spanLost(record.packetNumber, _outgoingPacketNumber + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// halve the rate and remember as threshold
|
// halve the rate and remember as threshold
|
||||||
|
@ -364,6 +376,8 @@ void DatagramSequencer::sendPacket(const QByteArray& packet, const QVector<Chann
|
||||||
_outputStream.getAndResetWriteMappings(), spans };
|
_outputStream.getAndResetWriteMappings(), spans };
|
||||||
_sendRecords.append(record);
|
_sendRecords.append(record);
|
||||||
|
|
||||||
|
emit sendRecorded();
|
||||||
|
|
||||||
// write the sequence number and size, which are the same between all fragments
|
// write the sequence number and size, which are the same between all fragments
|
||||||
_outgoingDatagramBuffer.seek(_datagramHeaderSize);
|
_outgoingDatagramBuffer.seek(_datagramHeaderSize);
|
||||||
_outgoingDatagramStream << (quint32)_outgoingPacketNumber;
|
_outgoingDatagramStream << (quint32)_outgoingPacketNumber;
|
||||||
|
@ -658,16 +672,24 @@ int ReliableChannel::getBytesAvailable() const {
|
||||||
return _buffer.size() - _acknowledged.getTotalSet();
|
return _buffer.size() - _acknowledged.getTotalSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReliableChannel::sendMessage(const QVariant& message) {
|
void ReliableChannel::startMessage() {
|
||||||
// write a placeholder for the length, then fill it in when we know what it is
|
// write a placeholder for the length; we'll fill it in when we know what it is
|
||||||
int placeholder = _buffer.pos();
|
_messageLengthPlaceholder = _buffer.pos();
|
||||||
_dataStream << (quint32)0;
|
_dataStream << (quint32)0;
|
||||||
_bitstream << message;
|
}
|
||||||
|
|
||||||
|
void ReliableChannel::endMessage() {
|
||||||
_bitstream.flush();
|
_bitstream.flush();
|
||||||
_bitstream.persistAndResetWriteMappings();
|
_bitstream.persistAndResetWriteMappings();
|
||||||
|
|
||||||
quint32 length = _buffer.pos() - placeholder;
|
quint32 length = _buffer.pos() - _messageLengthPlaceholder;
|
||||||
_buffer.writeBytes(placeholder, sizeof(quint32), (const char*)&length);
|
_buffer.writeBytes(_messageLengthPlaceholder, sizeof(quint32), (const char*)&length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReliableChannel::sendMessage(const QVariant& message) {
|
||||||
|
startMessage();
|
||||||
|
_bitstream << message;
|
||||||
|
endMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReliableChannel::sendClearSharedObjectMessage(int id) {
|
void ReliableChannel::sendClearSharedObjectMessage(int id) {
|
||||||
|
@ -675,7 +697,7 @@ void ReliableChannel::sendClearSharedObjectMessage(int id) {
|
||||||
sendMessage(QVariant::fromValue(message));
|
sendMessage(QVariant::fromValue(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReliableChannel::handleMessage(const QVariant& message) {
|
void ReliableChannel::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
if (message.userType() == ClearSharedObjectMessage::Type) {
|
if (message.userType() == ClearSharedObjectMessage::Type) {
|
||||||
_bitstream.clearSharedObject(message.value<ClearSharedObjectMessage>().id);
|
_bitstream.clearSharedObject(message.value<ClearSharedObjectMessage>().id);
|
||||||
|
|
||||||
|
@ -688,6 +710,7 @@ void ReliableChannel::handleMessage(const QVariant& message) {
|
||||||
ReliableChannel::ReliableChannel(DatagramSequencer* sequencer, int index, bool output) :
|
ReliableChannel::ReliableChannel(DatagramSequencer* sequencer, int index, bool output) :
|
||||||
QObject(sequencer),
|
QObject(sequencer),
|
||||||
_index(index),
|
_index(index),
|
||||||
|
_output(output),
|
||||||
_dataStream(&_buffer),
|
_dataStream(&_buffer),
|
||||||
_bitstream(_dataStream),
|
_bitstream(_dataStream),
|
||||||
_priority(1.0f),
|
_priority(1.0f),
|
||||||
|
@ -700,7 +723,9 @@ ReliableChannel::ReliableChannel(DatagramSequencer* sequencer, int index, bool o
|
||||||
_dataStream.setByteOrder(QDataStream::LittleEndian);
|
_dataStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
connect(&_bitstream, SIGNAL(sharedObjectCleared(int)), SLOT(sendClearSharedObjectMessage(int)));
|
connect(&_bitstream, SIGNAL(sharedObjectCleared(int)), SLOT(sendClearSharedObjectMessage(int)));
|
||||||
connect(this, SIGNAL(receivedMessage(const QVariant&)), SLOT(handleMessage(const QVariant&)));
|
connect(this, SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&)));
|
||||||
|
|
||||||
|
sequencer->connect(this, SIGNAL(destroyed(QObject*)), SLOT(clearReliableChannel(QObject*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReliableChannel::writeData(QDataStream& out, int bytes, QVector<DatagramSequencer::ChannelSpan>& spans) {
|
void ReliableChannel::writeData(QDataStream& out, int bytes, QVector<DatagramSequencer::ChannelSpan>& spans) {
|
||||||
|
@ -843,9 +868,9 @@ void ReliableChannel::readData(QDataStream& in) {
|
||||||
_dataStream.skipRawData(sizeof(quint32));
|
_dataStream.skipRawData(sizeof(quint32));
|
||||||
QVariant message;
|
QVariant message;
|
||||||
_bitstream >> message;
|
_bitstream >> message;
|
||||||
|
emit receivedMessage(message, _bitstream);
|
||||||
_bitstream.reset();
|
_bitstream.reset();
|
||||||
_bitstream.persistAndResetReadMappings();
|
_bitstream.persistAndResetReadMappings();
|
||||||
emit receivedMessage(message);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,15 @@ public:
|
||||||
/// Returns the packet number of the last packet received (or the packet currently being assembled).
|
/// Returns the packet number of the last packet received (or the packet currently being assembled).
|
||||||
int getIncomingPacketNumber() const { return _incomingPacketNumber; }
|
int getIncomingPacketNumber() const { return _incomingPacketNumber; }
|
||||||
|
|
||||||
|
/// Returns a reference to the stream used to read packets.
|
||||||
|
Bitstream& getInputStream() { return _inputStream; }
|
||||||
|
|
||||||
|
/// Returns a reference to the stream used to write packets.
|
||||||
|
Bitstream& getOutputStream() { return _outputStream; }
|
||||||
|
|
||||||
|
/// Returns a reference to the outgoing packet data.
|
||||||
|
const QByteArray& getOutgoingPacketData() const { return _outgoingPacketData; }
|
||||||
|
|
||||||
/// Returns the packet number of the sent packet at the specified index.
|
/// Returns the packet number of the sent packet at the specified index.
|
||||||
int getSentPacketNumber(int index) const { return _sendRecords.at(index).packetNumber; }
|
int getSentPacketNumber(int index) const { return _sendRecords.at(index).packetNumber; }
|
||||||
|
|
||||||
|
@ -126,9 +135,15 @@ signals:
|
||||||
/// Emitted when a packet is available to read.
|
/// Emitted when a packet is available to read.
|
||||||
void readyToRead(Bitstream& input);
|
void readyToRead(Bitstream& input);
|
||||||
|
|
||||||
/// Emitted when we've received a high-priority message
|
/// Emitted when we've received a high-priority message.
|
||||||
void receivedHighPriorityMessage(const QVariant& data);
|
void receivedHighPriorityMessage(const QVariant& data);
|
||||||
|
|
||||||
|
/// Emitted when we've recorded the transmission of a packet.
|
||||||
|
void sendRecorded();
|
||||||
|
|
||||||
|
/// Emitted when we've recorded the receipt of a packet (that is, at the end of packet processing).
|
||||||
|
void receiveRecorded();
|
||||||
|
|
||||||
/// Emitted when a sent packet has been acknowledged by the remote side.
|
/// Emitted when a sent packet has been acknowledged by the remote side.
|
||||||
/// \param index the index of the packet in our list of send records
|
/// \param index the index of the packet in our list of send records
|
||||||
void sendAcknowledged(int index);
|
void sendAcknowledged(int index);
|
||||||
|
@ -141,6 +156,7 @@ private slots:
|
||||||
|
|
||||||
void sendClearSharedObjectMessage(int id);
|
void sendClearSharedObjectMessage(int id);
|
||||||
void handleHighPriorityMessage(const QVariant& data);
|
void handleHighPriorityMessage(const QVariant& data);
|
||||||
|
void clearReliableChannel(QObject* object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -319,6 +335,9 @@ public:
|
||||||
/// Returns the channel's index in the sequencer's channel map.
|
/// Returns the channel's index in the sequencer's channel map.
|
||||||
int getIndex() const { return _index; }
|
int getIndex() const { return _index; }
|
||||||
|
|
||||||
|
/// Checks whether this is an output channel.
|
||||||
|
bool isOutput() const { return _output; }
|
||||||
|
|
||||||
/// Returns a reference to the buffer used to write/read data to/from this channel.
|
/// Returns a reference to the buffer used to write/read data to/from this channel.
|
||||||
CircularBuffer& getBuffer() { return _buffer; }
|
CircularBuffer& getBuffer() { return _buffer; }
|
||||||
|
|
||||||
|
@ -336,22 +355,36 @@ public:
|
||||||
/// Returns the number of bytes available to read from this channel.
|
/// Returns the number of bytes available to read from this channel.
|
||||||
int getBytesAvailable() const;
|
int getBytesAvailable() const;
|
||||||
|
|
||||||
|
/// Returns the offset, which represents the total number of bytes acknowledged
|
||||||
|
/// (on the write end) or received completely (on the read end).
|
||||||
|
int getOffset() const { return _offset; }
|
||||||
|
|
||||||
|
/// Returns the total number of bytes written to this channel.
|
||||||
|
int getBytesWritten() const { return _offset + _buffer.pos(); }
|
||||||
|
|
||||||
/// Sets whether we expect to write/read framed messages.
|
/// Sets whether we expect to write/read framed messages.
|
||||||
void setMessagesEnabled(bool enabled) { _messagesEnabled = enabled; }
|
void setMessagesEnabled(bool enabled) { _messagesEnabled = enabled; }
|
||||||
bool getMessagesEnabled() const { return _messagesEnabled; }
|
bool getMessagesEnabled() const { return _messagesEnabled; }
|
||||||
|
|
||||||
/// Sends a framed message on this channel.
|
/// Starts a framed message on this channel.
|
||||||
|
void startMessage();
|
||||||
|
|
||||||
|
/// Ends a framed message on this channel.
|
||||||
|
void endMessage();
|
||||||
|
|
||||||
|
/// Sends a framed message on this channel (convenience function that calls startMessage,
|
||||||
|
/// writes the message to the bitstream, then calls endMessage).
|
||||||
void sendMessage(const QVariant& message);
|
void sendMessage(const QVariant& message);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/// Fired when a framed message has been received on this channel.
|
/// Fired when a framed message has been received on this channel.
|
||||||
void receivedMessage(const QVariant& message);
|
void receivedMessage(const QVariant& message, Bitstream& in);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void sendClearSharedObjectMessage(int id);
|
void sendClearSharedObjectMessage(int id);
|
||||||
void handleMessage(const QVariant& message);
|
void handleMessage(const QVariant& message, Bitstream& in);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -370,6 +403,7 @@ private:
|
||||||
void readData(QDataStream& in);
|
void readData(QDataStream& in);
|
||||||
|
|
||||||
int _index;
|
int _index;
|
||||||
|
bool _output;
|
||||||
CircularBuffer _buffer;
|
CircularBuffer _buffer;
|
||||||
CircularBuffer _assemblyBuffer;
|
CircularBuffer _assemblyBuffer;
|
||||||
QDataStream _dataStream;
|
QDataStream _dataStream;
|
||||||
|
@ -381,6 +415,7 @@ private:
|
||||||
int _writePositionResetPacketNumber;
|
int _writePositionResetPacketNumber;
|
||||||
SpanList _acknowledged;
|
SpanList _acknowledged;
|
||||||
bool _messagesEnabled;
|
bool _messagesEnabled;
|
||||||
|
int _messageLengthPlaceholder;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DatagramSequencer_h
|
#endif // hifi_DatagramSequencer_h
|
||||||
|
|
|
@ -19,6 +19,8 @@ Endpoint::Endpoint(const SharedNodePointer& node, PacketRecord* baselineSendReco
|
||||||
|
|
||||||
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendDatagram(const QByteArray&)));
|
connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendDatagram(const QByteArray&)));
|
||||||
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readMessage(Bitstream&)));
|
connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readMessage(Bitstream&)));
|
||||||
|
connect(&_sequencer, SIGNAL(sendRecorded()), SLOT(recordSend()));
|
||||||
|
connect(&_sequencer, SIGNAL(receiveRecorded()), SLOT(recordReceive()));
|
||||||
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(clearSendRecordsBefore(int)));
|
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(clearSendRecordsBefore(int)));
|
||||||
connect(&_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int)));
|
connect(&_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int)));
|
||||||
|
|
||||||
|
@ -40,9 +42,6 @@ void Endpoint::update() {
|
||||||
Bitstream& out = _sequencer.startPacket();
|
Bitstream& out = _sequencer.startPacket();
|
||||||
writeUpdateMessage(out);
|
writeUpdateMessage(out);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
|
|
||||||
// record the send
|
|
||||||
_sendRecords.append(maybeCreateSendRecord());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Endpoint::parseData(const QByteArray& packet) {
|
int Endpoint::parseData(const QByteArray& packet) {
|
||||||
|
@ -59,8 +58,21 @@ void Endpoint::readMessage(Bitstream& in) {
|
||||||
QVariant message;
|
QVariant message;
|
||||||
in >> message;
|
in >> message;
|
||||||
handleMessage(message, in);
|
handleMessage(message, in);
|
||||||
|
}
|
||||||
// record the receipt
|
|
||||||
|
void Endpoint::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
if (message.userType() == QMetaType::QVariantList) {
|
||||||
|
foreach (const QVariant& element, message.toList()) {
|
||||||
|
handleMessage(element, in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Endpoint::recordSend() {
|
||||||
|
_sendRecords.append(maybeCreateSendRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Endpoint::recordReceive() {
|
||||||
_receiveRecords.append(maybeCreateReceiveRecord());
|
_receiveRecords.append(maybeCreateReceiveRecord());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,14 +96,6 @@ void Endpoint::writeUpdateMessage(Bitstream& out) {
|
||||||
out << QVariant();
|
out << QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Endpoint::handleMessage(const QVariant& message, Bitstream& in) {
|
|
||||||
if (message.userType() == QMetaType::QVariantList) {
|
|
||||||
foreach (const QVariant& element, message.toList()) {
|
|
||||||
handleMessage(element, in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketRecord* Endpoint::maybeCreateSendRecord() const {
|
PacketRecord* Endpoint::maybeCreateSendRecord() const {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@ class Endpoint : public NodeData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// The index of the input/output channel used to transmit reliable deltas.
|
||||||
|
static const int RELIABLE_DELTA_CHANNEL_INDEX = 1;
|
||||||
|
|
||||||
Endpoint(const SharedNodePointer& node, PacketRecord* baselineSendRecord = NULL,
|
Endpoint(const SharedNodePointer& node, PacketRecord* baselineSendRecord = NULL,
|
||||||
PacketRecord* baselineReceiveRecord = NULL);
|
PacketRecord* baselineReceiveRecord = NULL);
|
||||||
|
@ -37,6 +40,10 @@ protected slots:
|
||||||
|
|
||||||
virtual void sendDatagram(const QByteArray& data);
|
virtual void sendDatagram(const QByteArray& data);
|
||||||
virtual void readMessage(Bitstream& in);
|
virtual void readMessage(Bitstream& in);
|
||||||
|
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
||||||
|
|
||||||
|
void recordSend();
|
||||||
|
void recordReceive();
|
||||||
|
|
||||||
void clearSendRecordsBefore(int index);
|
void clearSendRecordsBefore(int index);
|
||||||
void clearReceiveRecordsBefore(int index);
|
void clearReceiveRecordsBefore(int index);
|
||||||
|
@ -44,7 +51,6 @@ protected slots:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void writeUpdateMessage(Bitstream& out);
|
virtual void writeUpdateMessage(Bitstream& out);
|
||||||
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
|
||||||
|
|
||||||
virtual PacketRecord* maybeCreateSendRecord() const;
|
virtual PacketRecord* maybeCreateSendRecord() const;
|
||||||
virtual PacketRecord* maybeCreateReceiveRecord() const;
|
virtual PacketRecord* maybeCreateReceiveRecord() const;
|
||||||
|
|
|
@ -86,7 +86,11 @@ void MetavoxelClientManager::updateClient(MetavoxelClient* client) {
|
||||||
|
|
||||||
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node, MetavoxelClientManager* manager) :
|
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node, MetavoxelClientManager* manager) :
|
||||||
Endpoint(node, new PacketRecord(), new PacketRecord()),
|
Endpoint(node, new PacketRecord(), new PacketRecord()),
|
||||||
_manager(manager) {
|
_manager(manager),
|
||||||
|
_reliableDeltaChannel(NULL) {
|
||||||
|
|
||||||
|
connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX),
|
||||||
|
SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelClient::guide(MetavoxelVisitor& visitor) {
|
void MetavoxelClient::guide(MetavoxelVisitor& visitor) {
|
||||||
|
@ -112,31 +116,44 @@ void MetavoxelClient::writeUpdateMessage(Bitstream& out) {
|
||||||
out << QVariant::fromValue(state);
|
out << QVariant::fromValue(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelClient::readMessage(Bitstream& in) {
|
|
||||||
Endpoint::readMessage(in);
|
|
||||||
|
|
||||||
// reapply local edits
|
|
||||||
foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) {
|
|
||||||
if (message.data.userType() == MetavoxelEditMessage::Type) {
|
|
||||||
message.data.value<MetavoxelEditMessage>().apply(_data, _sequencer.getWeakSharedObjectHash());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {
|
void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
if (message.userType() == MetavoxelDeltaMessage::Type) {
|
int userType = message.userType();
|
||||||
|
if (userType == MetavoxelDeltaMessage::Type) {
|
||||||
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, getLastAcknowledgedSendRecord()->getLOD());
|
if (_reliableDeltaChannel) {
|
||||||
|
_remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _remoteDataLOD = _reliableDeltaLOD);
|
||||||
|
_sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings());
|
||||||
|
in.clearPersistentMappings();
|
||||||
|
_reliableDeltaChannel = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in,
|
||||||
|
_remoteDataLOD = getLastAcknowledgedSendRecord()->getLOD());
|
||||||
|
in.reset();
|
||||||
|
}
|
||||||
|
// copy to local and reapply local edits
|
||||||
|
_data = _remoteData;
|
||||||
|
foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) {
|
||||||
|
if (message.data.userType() == MetavoxelEditMessage::Type) {
|
||||||
|
message.data.value<MetavoxelEditMessage>().apply(_data, _sequencer.getWeakSharedObjectHash());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
||||||
|
if (!_reliableDeltaChannel) {
|
||||||
|
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
|
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
||||||
|
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Endpoint::handleMessage(message, in);
|
Endpoint::handleMessage(message, in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* MetavoxelClient::maybeCreateSendRecord() const {
|
PacketRecord* MetavoxelClient::maybeCreateSendRecord() const {
|
||||||
return new PacketRecord(_manager->getLOD());
|
return new PacketRecord(_reliableDeltaChannel ? _reliableDeltaLOD : _manager->getLOD());
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* MetavoxelClient::maybeCreateReceiveRecord() const {
|
PacketRecord* MetavoxelClient::maybeCreateReceiveRecord() const {
|
||||||
return new PacketRecord(getLastAcknowledgedSendRecord()->getLOD(), _data);
|
return new PacketRecord(_remoteDataLOD, _remoteData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void writeUpdateMessage(Bitstream& out);
|
virtual void writeUpdateMessage(Bitstream& out);
|
||||||
virtual void readMessage(Bitstream& in);
|
|
||||||
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
virtual void handleMessage(const QVariant& message, Bitstream& in);
|
||||||
|
|
||||||
virtual PacketRecord* maybeCreateSendRecord() const;
|
virtual PacketRecord* maybeCreateSendRecord() const;
|
||||||
|
@ -70,6 +69,11 @@ private:
|
||||||
|
|
||||||
MetavoxelClientManager* _manager;
|
MetavoxelClientManager* _manager;
|
||||||
MetavoxelData _data;
|
MetavoxelData _data;
|
||||||
|
MetavoxelData _remoteData;
|
||||||
|
MetavoxelLOD _remoteDataLOD;
|
||||||
|
|
||||||
|
ReliableChannel* _reliableDeltaChannel;
|
||||||
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelClientManager_h
|
#endif // hifi_MetavoxelClientManager_h
|
||||||
|
|
|
@ -61,6 +61,13 @@ class MetavoxelDeltaMessage {
|
||||||
|
|
||||||
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaMessage)
|
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaMessage)
|
||||||
|
|
||||||
|
/// A message indicating that metavoxel delta information is being sent on a reliable channel.
|
||||||
|
class MetavoxelDeltaPendingMessage {
|
||||||
|
STREAMABLE
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage)
|
||||||
|
|
||||||
/// A simple streamable edit.
|
/// A simple streamable edit.
|
||||||
class MetavoxelEditMessage {
|
class MetavoxelEditMessage {
|
||||||
STREAMABLE
|
STREAMABLE
|
||||||
|
|
|
@ -9,141 +9,19 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QMetaObject>
|
#include <QThreadStorage>
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#include "NetworkAccessManager.h"
|
#include "NetworkAccessManager.h"
|
||||||
|
|
||||||
|
QThreadStorage<NetworkAccessManager*> networkAccessManagers;
|
||||||
|
|
||||||
NetworkAccessManager& NetworkAccessManager::getInstance() {
|
NetworkAccessManager& NetworkAccessManager::getInstance() {
|
||||||
static NetworkAccessManager sharedInstance;
|
if (!networkAccessManagers.hasLocalData()) {
|
||||||
return sharedInstance;
|
networkAccessManagers.setLocalData(new NetworkAccessManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
return *networkAccessManagers.localData();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkAccessManager::NetworkAccessManager() {
|
NetworkAccessManager::NetworkAccessManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::get(const QNetworkRequest& request) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"get",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::get(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::head(const QNetworkRequest& request) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"head",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::head(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QIODevice* data) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"post",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(QIODevice*, data));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::post(request, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, const QByteArray& data) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"post",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(const QByteArray, data));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::post(request, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"post",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(QHttpMultiPart*, multiPart));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::post(request, multiPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QIODevice* data) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"put",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(QIODevice*, data));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::put(request, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"put",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(QHttpMultiPart*, multiPart));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::put(request, multiPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest & request, const QByteArray & data) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"put",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(const QByteArray, data));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::put(request, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QNetworkReply* NetworkAccessManager::sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QNetworkReply* result;
|
|
||||||
QMetaObject::invokeMethod(this,
|
|
||||||
"sendCustomRequest",
|
|
||||||
Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QNetworkReply*, result),
|
|
||||||
Q_ARG(const QNetworkRequest, request),
|
|
||||||
Q_ARG(const QByteArray, verb),
|
|
||||||
Q_ARG(QIODevice*, data));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return QNetworkAccessManager::sendCustomRequest(request, verb, data);
|
|
||||||
}
|
|
|
@ -13,27 +13,13 @@
|
||||||
#define hifi_NetworkAccessManager_h
|
#define hifi_NetworkAccessManager_h
|
||||||
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkConfiguration>
|
|
||||||
#include <QNetworkProxy>
|
|
||||||
|
|
||||||
/// Wrapper around QNetworkAccessManager wo that we only use one instance
|
/// Wrapper around QNetworkAccessManager to restrict at one instance by thread
|
||||||
/// For any other method you should need, make sure to be on the right thread
|
|
||||||
/// or call the method using QMetaObject::invokeMethod()
|
|
||||||
class NetworkAccessManager : public QNetworkAccessManager {
|
class NetworkAccessManager : public QNetworkAccessManager {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static NetworkAccessManager& getInstance();
|
static NetworkAccessManager& getInstance();
|
||||||
|
|
||||||
Q_INVOKABLE QNetworkReply* get(const QNetworkRequest& request);
|
|
||||||
Q_INVOKABLE QNetworkReply* head(const QNetworkRequest& request);
|
|
||||||
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QIODevice* data);
|
|
||||||
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, const QByteArray& data);
|
|
||||||
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QHttpMultiPart* multiPart);
|
|
||||||
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QIODevice* data);
|
|
||||||
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QHttpMultiPart* multiPart);
|
|
||||||
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, const QByteArray& data);
|
|
||||||
Q_INVOKABLE QNetworkReply* sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data = 0);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetworkAccessManager();
|
NetworkAccessManager();
|
||||||
};
|
};
|
||||||
|
|
|
@ -646,16 +646,23 @@ TestEndpoint::TestEndpoint(Mode mode) :
|
||||||
Endpoint(SharedNodePointer(), new TestSendRecord(), new TestReceiveRecord()),
|
Endpoint(SharedNodePointer(), new TestSendRecord(), new TestReceiveRecord()),
|
||||||
_mode(mode),
|
_mode(mode),
|
||||||
_highPriorityMessagesToSend(0.0f),
|
_highPriorityMessagesToSend(0.0f),
|
||||||
_reliableMessagesToSend(0.0f) {
|
_reliableMessagesToSend(0.0f),
|
||||||
|
_reliableDeltaChannel(NULL) {
|
||||||
|
|
||||||
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)),
|
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)),
|
||||||
SLOT(handleHighPriorityMessage(const QVariant&)));
|
SLOT(handleHighPriorityMessage(const QVariant&)));
|
||||||
|
connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&, Bitstream&)),
|
||||||
|
SLOT(handleReliableMessage(const QVariant&, Bitstream&)));
|
||||||
|
|
||||||
if (mode == METAVOXEL_CLIENT_MODE) {
|
if (mode == METAVOXEL_CLIENT_MODE) {
|
||||||
_lod = MetavoxelLOD(glm::vec3(), 0.01f);
|
_lod = MetavoxelLOD(glm::vec3(), 0.01f);
|
||||||
|
connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX),
|
||||||
|
SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleReliableMessage(const QVariant&, Bitstream&)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mode == METAVOXEL_SERVER_MODE) {
|
if (mode == METAVOXEL_SERVER_MODE) {
|
||||||
|
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived()));
|
||||||
|
|
||||||
_data.expand();
|
_data.expand();
|
||||||
_data.expand();
|
_data.expand();
|
||||||
|
|
||||||
|
@ -673,9 +680,6 @@ TestEndpoint::TestEndpoint(Mode mode) :
|
||||||
// create the object that represents out delta-encoded state
|
// create the object that represents out delta-encoded state
|
||||||
_localState = new TestSharedObjectA();
|
_localState = new TestSharedObjectA();
|
||||||
|
|
||||||
connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&)),
|
|
||||||
SLOT(handleReliableMessage(const QVariant&)));
|
|
||||||
|
|
||||||
ReliableChannel* secondInput = _sequencer.getReliableInputChannel(1);
|
ReliableChannel* secondInput = _sequencer.getReliableInputChannel(1);
|
||||||
secondInput->setMessagesEnabled(false);
|
secondInput->setMessagesEnabled(false);
|
||||||
connect(&secondInput->getBuffer(), SIGNAL(readyRead()), SLOT(readReliableChannel()));
|
connect(&secondInput->getBuffer(), SIGNAL(readyRead()), SLOT(readReliableChannel()));
|
||||||
|
@ -867,9 +871,6 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
|
|
||||||
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
||||||
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
||||||
|
|
||||||
// record the send
|
|
||||||
_sendRecords.append(maybeCreateSendRecord());
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -880,9 +881,6 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
out << QVariant::fromValue(state);
|
out << QVariant::fromValue(state);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
|
|
||||||
// record the send
|
|
||||||
_sendRecords.append(maybeCreateSendRecord());
|
|
||||||
|
|
||||||
} else if (_mode == METAVOXEL_SERVER_MODE) {
|
} else if (_mode == METAVOXEL_SERVER_MODE) {
|
||||||
// make a random change
|
// make a random change
|
||||||
MutateVisitor visitor;
|
MutateVisitor visitor;
|
||||||
|
@ -907,15 +905,39 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
if (!_lod.isValid()) {
|
if (!_lod.isValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// if we're sending a reliable delta, wait until it's acknowledged
|
||||||
|
if (_reliableDeltaChannel) {
|
||||||
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
||||||
|
_sequencer.endPacket();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Bitstream& out = _sequencer.startPacket();
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
int start = _sequencer.getOutputStream().getUnderlying().device()->pos();
|
||||||
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
||||||
PacketRecord* sendRecord = getLastAcknowledgedSendRecord();
|
PacketRecord* sendRecord = getLastAcknowledgedSendRecord();
|
||||||
_data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod);
|
_data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod);
|
||||||
_sequencer.endPacket();
|
out.flush();
|
||||||
|
int end = _sequencer.getOutputStream().getUnderlying().device()->pos();
|
||||||
// record the send
|
if (end > _sequencer.getMaxPacketSize()) {
|
||||||
_sendRecords.append(maybeCreateSendRecord());
|
// we need to send the delta on the reliable channel
|
||||||
|
_reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
|
_reliableDeltaChannel->startMessage();
|
||||||
|
_reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start);
|
||||||
|
_reliableDeltaChannel->endMessage();
|
||||||
|
|
||||||
|
_reliableDeltaWriteMappings = out.getAndResetWriteMappings();
|
||||||
|
_reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten();
|
||||||
|
_reliableDeltaData = _data;
|
||||||
|
_reliableDeltaLOD = _lod;
|
||||||
|
|
||||||
|
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
||||||
|
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
||||||
|
_sequencer.endPacket();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_sequencer.endPacket();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// enqueue some number of high priority messages
|
// enqueue some number of high priority messages
|
||||||
const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f;
|
const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f;
|
||||||
|
@ -957,9 +979,6 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
qDebug() << message;
|
qDebug() << message;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// record the send
|
|
||||||
_sendRecords.append(maybeCreateSendRecord());
|
|
||||||
}
|
}
|
||||||
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
||||||
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
||||||
|
@ -995,7 +1014,7 @@ void TestEndpoint::sendDatagram(const QByteArray& datagram) {
|
||||||
// some are received out of order
|
// some are received out of order
|
||||||
const float REORDER_PROBABILITY = 0.1f;
|
const float REORDER_PROBABILITY = 0.1f;
|
||||||
if (randFloat() < REORDER_PROBABILITY * probabilityMultiplier) {
|
if (randFloat() < REORDER_PROBABILITY * probabilityMultiplier) {
|
||||||
const int MIN_DELAY = 1;
|
const int MIN_DELAY = 2;
|
||||||
const int MAX_DELAY = 5;
|
const int MAX_DELAY = 5;
|
||||||
// have to copy the datagram; the one we're passed is a reference to a shared buffer
|
// have to copy the datagram; the one we're passed is a reference to a shared buffer
|
||||||
_delayedDatagrams.append(ByteArrayIntPair(QByteArray(datagram.constData(), datagram.size()),
|
_delayedDatagrams.append(ByteArrayIntPair(QByteArray(datagram.constData(), datagram.size()),
|
||||||
|
@ -1008,58 +1027,32 @@ void TestEndpoint::sendDatagram(const QByteArray& datagram) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_other->parseData(datagram);
|
_delayedDatagrams.append(ByteArrayIntPair(QByteArray(datagram.constData(), datagram.size()), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEndpoint::readMessage(Bitstream& in) {
|
void TestEndpoint::readMessage(Bitstream& in) {
|
||||||
if (_mode == CONGESTION_MODE) {
|
if (_mode == CONGESTION_MODE) {
|
||||||
QVariant message;
|
QVariant message;
|
||||||
in >> message;
|
in >> message;
|
||||||
|
|
||||||
// record the receipt
|
|
||||||
_receiveRecords.append(maybeCreateReceiveRecord());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_mode == METAVOXEL_CLIENT_MODE) {
|
if (_mode == METAVOXEL_CLIENT_MODE) {
|
||||||
QVariant message;
|
QVariant message;
|
||||||
in >> message;
|
in >> message;
|
||||||
handleMessage(message, in);
|
handleMessage(message, in);
|
||||||
|
|
||||||
// deep-compare data to sent version
|
|
||||||
int packetNumber = _sequencer.getIncomingPacketNumber();
|
|
||||||
foreach (PacketRecord* record, _other->_sendRecords) {
|
|
||||||
TestSendRecord* sendRecord = static_cast<TestSendRecord*>(record);
|
|
||||||
if (sendRecord->getPacketNumber() == packetNumber) {
|
|
||||||
if (!sendRecord->getData().deepEquals(_data, getLastAcknowledgedSendRecord()->getLOD())) {
|
|
||||||
qDebug() << "Sent/received metavoxel data mismatch.";
|
|
||||||
exit(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// record the receipt
|
|
||||||
_receiveRecords.append(maybeCreateReceiveRecord());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_mode == METAVOXEL_SERVER_MODE) {
|
if (_mode == METAVOXEL_SERVER_MODE) {
|
||||||
QVariant message;
|
QVariant message;
|
||||||
in >> message;
|
in >> message;
|
||||||
handleMessage(message, in);
|
handleMessage(message, in);
|
||||||
|
|
||||||
// record the receipt
|
|
||||||
_receiveRecords.append(maybeCreateReceiveRecord());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SequencedTestMessage message;
|
SequencedTestMessage message;
|
||||||
in >> message;
|
in >> message;
|
||||||
|
|
||||||
_remoteState = message.state;
|
_remoteState = message.state;
|
||||||
|
|
||||||
// record the receipt
|
|
||||||
_receiveRecords.append(maybeCreateReceiveRecord());
|
|
||||||
|
|
||||||
for (QList<SequencedTestMessage>::iterator it = _other->_unreliableMessagesSent.begin();
|
for (QList<SequencedTestMessage>::iterator it = _other->_unreliableMessagesSent.begin();
|
||||||
it != _other->_unreliableMessagesSent.end(); it++) {
|
it != _other->_unreliableMessagesSent.end(); it++) {
|
||||||
if (it->sequenceNumber == message.sequenceNumber) {
|
if (it->sequenceNumber == message.sequenceNumber) {
|
||||||
|
@ -1088,8 +1081,16 @@ void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
|
||||||
} else if (userType == MetavoxelDeltaMessage::Type) {
|
} else if (userType == MetavoxelDeltaMessage::Type) {
|
||||||
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, getLastAcknowledgedSendRecord()->getLOD());
|
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in,
|
||||||
|
_dataLOD = getLastAcknowledgedSendRecord()->getLOD());
|
||||||
|
compareMetavoxelData();
|
||||||
|
|
||||||
|
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
||||||
|
if (!_reliableDeltaChannel) {
|
||||||
|
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
|
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
||||||
|
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
||||||
|
}
|
||||||
} else if (userType == QMetaType::QVariantList) {
|
} else if (userType == QMetaType::QVariantList) {
|
||||||
foreach (const QVariant& element, message.toList()) {
|
foreach (const QVariant& element, message.toList()) {
|
||||||
handleMessage(element, in);
|
handleMessage(element, in);
|
||||||
|
@ -1098,13 +1099,15 @@ void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* TestEndpoint::maybeCreateSendRecord() const {
|
PacketRecord* TestEndpoint::maybeCreateSendRecord() const {
|
||||||
|
if (_reliableDeltaChannel) {
|
||||||
|
return new TestSendRecord(_reliableDeltaLOD, _reliableDeltaData, _localState, _sequencer.getOutgoingPacketNumber());
|
||||||
|
}
|
||||||
return new TestSendRecord(_lod, (_mode == METAVOXEL_CLIENT_MODE) ? MetavoxelData() : _data,
|
return new TestSendRecord(_lod, (_mode == METAVOXEL_CLIENT_MODE) ? MetavoxelData() : _data,
|
||||||
_localState, _sequencer.getOutgoingPacketNumber());
|
_localState, _sequencer.getOutgoingPacketNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const {
|
PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const {
|
||||||
return new TestReceiveRecord(getLastAcknowledgedSendRecord()->getLOD(),
|
return new TestReceiveRecord(_dataLOD, (_mode == METAVOXEL_SERVER_MODE) ? MetavoxelData() : _data, _remoteState);
|
||||||
(_mode == METAVOXEL_SERVER_MODE) ? MetavoxelData() : _data, _remoteState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
||||||
|
@ -1121,7 +1124,16 @@ void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
||||||
highPriorityMessagesReceived++;
|
highPriorityMessagesReceived++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEndpoint::handleReliableMessage(const QVariant& message) {
|
void TestEndpoint::handleReliableMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
if (message.userType() == MetavoxelDeltaMessage::Type) {
|
||||||
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
|
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _dataLOD = _reliableDeltaLOD);
|
||||||
|
_sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings());
|
||||||
|
in.clearPersistentMappings();
|
||||||
|
compareMetavoxelData();
|
||||||
|
_reliableDeltaChannel = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (message.userType() == ClearSharedObjectMessage::Type ||
|
if (message.userType() == ClearSharedObjectMessage::Type ||
|
||||||
message.userType() == ClearMainChannelSharedObjectMessage::Type) {
|
message.userType() == ClearMainChannelSharedObjectMessage::Type) {
|
||||||
return;
|
return;
|
||||||
|
@ -1150,6 +1162,33 @@ void TestEndpoint::readReliableChannel() {
|
||||||
streamedBytesReceived += bytes.size();
|
streamedBytesReceived += bytes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestEndpoint::checkReliableDeltaReceived() {
|
||||||
|
if (!_reliableDeltaChannel || _reliableDeltaChannel->getOffset() < _reliableDeltaReceivedOffset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_sequencer.getOutputStream().persistWriteMappings(_reliableDeltaWriteMappings);
|
||||||
|
_reliableDeltaWriteMappings = Bitstream::WriteMappings();
|
||||||
|
_reliableDeltaData = MetavoxelData();
|
||||||
|
_reliableDeltaChannel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestEndpoint::compareMetavoxelData() {
|
||||||
|
// deep-compare data to sent version
|
||||||
|
int packetNumber = _sequencer.getIncomingPacketNumber();
|
||||||
|
foreach (PacketRecord* record, _other->_sendRecords) {
|
||||||
|
TestSendRecord* sendRecord = static_cast<TestSendRecord*>(record);
|
||||||
|
if (sendRecord->getPacketNumber() == packetNumber) {
|
||||||
|
if (!sendRecord->getData().deepEquals(_data, getLastAcknowledgedSendRecord()->getLOD())) {
|
||||||
|
qDebug() << "Sent/received metavoxel data mismatch.";
|
||||||
|
exit(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug() << "Received metavoxel data with no corresponding send." << packetNumber;
|
||||||
|
exit(true);
|
||||||
|
}
|
||||||
|
|
||||||
TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) :
|
TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) :
|
||||||
_foo(foo),
|
_foo(foo),
|
||||||
_baz(baz),
|
_baz(baz),
|
||||||
|
|
|
@ -64,17 +64,21 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void handleHighPriorityMessage(const QVariant& message);
|
void handleHighPriorityMessage(const QVariant& message);
|
||||||
void handleReliableMessage(const QVariant& message);
|
void handleReliableMessage(const QVariant& message, Bitstream& in);
|
||||||
void readReliableChannel();
|
void readReliableChannel();
|
||||||
|
void checkReliableDeltaReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void compareMetavoxelData();
|
||||||
|
|
||||||
Mode _mode;
|
Mode _mode;
|
||||||
|
|
||||||
SharedObjectPointer _localState;
|
SharedObjectPointer _localState;
|
||||||
SharedObjectPointer _remoteState;
|
SharedObjectPointer _remoteState;
|
||||||
|
|
||||||
MetavoxelData _data;
|
MetavoxelData _data;
|
||||||
|
MetavoxelLOD _dataLOD;
|
||||||
MetavoxelLOD _lod;
|
MetavoxelLOD _lod;
|
||||||
|
|
||||||
SharedObjectPointer _sphere;
|
SharedObjectPointer _sphere;
|
||||||
|
@ -94,6 +98,12 @@ private:
|
||||||
float _reliableMessagesToSend;
|
float _reliableMessagesToSend;
|
||||||
QVariantList _reliableMessagesSent;
|
QVariantList _reliableMessagesSent;
|
||||||
CircularBuffer _dataStreamed;
|
CircularBuffer _dataStreamed;
|
||||||
|
|
||||||
|
ReliableChannel* _reliableDeltaChannel;
|
||||||
|
int _reliableDeltaReceivedOffset;
|
||||||
|
MetavoxelData _reliableDeltaData;
|
||||||
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
|
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A simple shared object.
|
/// A simple shared object.
|
||||||
|
|
Loading…
Reference in a new issue