mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into brown
This commit is contained in:
commit
3727b2af7e
12 changed files with 114 additions and 83 deletions
|
@ -10,7 +10,6 @@
|
|||
<link href="/css/sweetalert.css" rel="stylesheet" media="screen">
|
||||
<link href="/css/bootstrap-switch.min.css" rel="stylesheet" media="screen">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
|
@ -38,8 +37,23 @@
|
|||
</li>
|
||||
<li><a href="/content/">Content</a></li>
|
||||
<li><a href="/settings/">Settings</a></li>
|
||||
<li><a href="#" id="restart-server"><span class="glyphicon glyphicon-refresh"></span> Restart</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
||||
|
||||
<div class="modal fade" id="restart-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">domain-server is restarting</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5>This page will automatically refresh in <span id="refresh-time">3 seconds</span>.</h5>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div class="container-fluid">
|
||||
|
|
|
@ -1,3 +1,28 @@
|
|||
function showRestartModal() {
|
||||
$('#restart-modal').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
});
|
||||
|
||||
var secondsElapsed = 0;
|
||||
var numberOfSecondsToWait = 3;
|
||||
|
||||
var refreshSpan = $('span#refresh-time')
|
||||
refreshSpan.html(numberOfSecondsToWait + " seconds");
|
||||
|
||||
// call ourselves every 1 second to countdown
|
||||
var refreshCountdown = setInterval(function(){
|
||||
secondsElapsed++;
|
||||
secondsLeft = numberOfSecondsToWait - secondsElapsed
|
||||
refreshSpan.html(secondsLeft + (secondsLeft == 1 ? " second" : " seconds"))
|
||||
|
||||
if (secondsElapsed == numberOfSecondsToWait) {
|
||||
location.reload(true);
|
||||
clearInterval(refreshCountdown);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
var url = window.location;
|
||||
// Will only work if string in href matches with location
|
||||
|
@ -7,4 +32,10 @@ $(document).ready(function(){
|
|||
$('ul.nav a').filter(function() {
|
||||
return this.href == url;
|
||||
}).parent().addClass('active');
|
||||
|
||||
$('body').on('click', '#restart-server', function(e){
|
||||
$.get("/restart");
|
||||
showRestartModal();
|
||||
return false;
|
||||
});
|
||||
});
|
|
@ -81,19 +81,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="restart-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">domain-server is restarting</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5>This page will automatically refresh in <span id="refresh-time">3 seconds</span>.</h5>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<!--#include virtual="footer.html"-->
|
||||
<script src='/js/underscore-min.js'></script>
|
||||
<script src='/js/underscore-keypath.min.js'></script>
|
||||
|
|
|
@ -1680,31 +1680,6 @@ function updateDataChangedForSiblingRows(row, forceTrue) {
|
|||
})
|
||||
}
|
||||
|
||||
function showRestartModal() {
|
||||
$('#restart-modal').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
});
|
||||
|
||||
var secondsElapsed = 0;
|
||||
var numberOfSecondsToWait = 3;
|
||||
|
||||
var refreshSpan = $('span#refresh-time')
|
||||
refreshSpan.html(numberOfSecondsToWait + " seconds");
|
||||
|
||||
// call ourselves every 1 second to countdown
|
||||
var refreshCountdown = setInterval(function(){
|
||||
secondsElapsed++;
|
||||
secondsLeft = numberOfSecondsToWait - secondsElapsed
|
||||
refreshSpan.html(secondsLeft + (secondsLeft == 1 ? " second" : " seconds"))
|
||||
|
||||
if (secondsElapsed == numberOfSecondsToWait) {
|
||||
location.reload(true);
|
||||
clearInterval(refreshCountdown);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function cleanupFormValues(node) {
|
||||
if (node.type && node.type === 'checkbox') {
|
||||
return { name: node.name, value: node.checked ? true : false };
|
||||
|
|
|
@ -1650,6 +1650,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
const QString URI_NODES = "/nodes";
|
||||
const QString URI_SETTINGS = "/settings";
|
||||
const QString URI_ENTITY_FILE_UPLOAD = "/content/upload";
|
||||
const QString URI_RESTART = "/restart";
|
||||
|
||||
const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
||||
|
||||
|
@ -1804,6 +1805,10 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
// send the response
|
||||
connection->respond(HTTPConnection::StatusCode200, nodesDocument.toJson(), qPrintable(JSON_MIME_TYPE));
|
||||
|
||||
return true;
|
||||
} else if (url.path() == URI_RESTART) {
|
||||
connection->respond(HTTPConnection::StatusCode200);
|
||||
restart();
|
||||
return true;
|
||||
} else {
|
||||
// check if this is for json stats for a node
|
||||
|
|
|
@ -18,7 +18,7 @@ import QtQuick.Layouts 1.3
|
|||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows"
|
||||
import "./" as Audio
|
||||
import "./" as AudioControls
|
||||
|
||||
Rectangle {
|
||||
id: root;
|
||||
|
@ -57,7 +57,7 @@ Rectangle {
|
|||
x: 16; // padding does not work
|
||||
spacing: 16;
|
||||
|
||||
Audio.CheckBox {
|
||||
AudioControls.CheckBox {
|
||||
text: qsTr("Mute microphone");
|
||||
checked: Audio.muted;
|
||||
onClicked: {
|
||||
|
@ -65,7 +65,7 @@ Rectangle {
|
|||
checked = Qt.binding(function() { return Audio.muted; }); // restore binding
|
||||
}
|
||||
}
|
||||
Audio.CheckBox {
|
||||
AudioControls.CheckBox {
|
||||
text: qsTr("Enable noise reduction");
|
||||
checked: Audio.noiseReduction;
|
||||
onClicked: {
|
||||
|
@ -73,7 +73,7 @@ Rectangle {
|
|||
checked = Qt.binding(function() { return Audio.noiseReduction; }); // restore binding
|
||||
}
|
||||
}
|
||||
Audio.CheckBox {
|
||||
AudioControls.CheckBox {
|
||||
text: qsTr("Show audio level meter");
|
||||
checked: AvatarInputs.showAudioTools;
|
||||
onClicked: {
|
||||
|
@ -110,7 +110,7 @@ Rectangle {
|
|||
delegate: Item {
|
||||
width: parent.width;
|
||||
height: 36;
|
||||
Audio.CheckBox {
|
||||
AudioControls.CheckBox {
|
||||
text: display;
|
||||
checked: selected;
|
||||
onClicked: {
|
||||
|
@ -148,7 +148,7 @@ Rectangle {
|
|||
delegate: Item {
|
||||
width: parent.width;
|
||||
height: 36;
|
||||
Audio.CheckBox {
|
||||
AudioControls.CheckBox {
|
||||
text: display;
|
||||
checked: selected;
|
||||
onClicked: {
|
||||
|
|
|
@ -386,7 +386,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
return 0;
|
||||
}
|
||||
|
||||
qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
||||
int64_t clockSkew = 0;
|
||||
uint64_t maxPingRoundTrip = 33333; // two frames periods at 60 fps
|
||||
if (args.sourceNode) {
|
||||
clockSkew = args.sourceNode->getClockSkewUsec();
|
||||
const float MSECS_PER_USEC = 1000;
|
||||
maxPingRoundTrip += args.sourceNode->getPingMs() * MSECS_PER_USEC;
|
||||
}
|
||||
|
||||
BufferParser parser(data, bytesLeftToRead);
|
||||
|
||||
|
@ -653,7 +659,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
|
||||
|
||||
// pack SimulationOwner and terse update properties near each other
|
||||
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
|
||||
// even when we would otherwise ignore the rest of the packet.
|
||||
|
@ -678,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) {
|
||||
// entity-server is trying to clear our ownership (probably at our own request)
|
||||
// but we actually want to own it, therefore we ignore this clear event
|
||||
// and pretend that we own it (we assume we'll recover it soon)
|
||||
// and pretend that we own it (e.g. we assume we'll receive ownership soon)
|
||||
|
||||
// However, for now, when the server uses a newer time than what we sent, listen to what we're told.
|
||||
if (overwriteLocalData) {
|
||||
|
@ -690,16 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
// recompute weOwnSimulation for later
|
||||
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
}
|
||||
} else if (newSimOwner.getID().isNull() && _simulationOwner.pendingTake(lastEditedFromBufferAdjusted)) {
|
||||
// entity-server is trying to clear someone else's ownership
|
||||
// but we want to own it, therefore we ignore this clear event
|
||||
// and pretend that we own it (we assume we'll get it soon)
|
||||
} else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) {
|
||||
// we sent a bid before this packet could have been sent from the server
|
||||
// so we ignore it and pretend we own the object's simulation
|
||||
weOwnSimulation = true;
|
||||
if (!_simulationOwner.isNull()) {
|
||||
// someone else really did own it
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
somethingChanged = true;
|
||||
_simulationOwner.clearCurrentOwner();
|
||||
if (newSimOwner.getID().isNull()) {
|
||||
// entity-server is trying to clear someone else's ownership
|
||||
// but we want to own it, therefore we ignore this clear event
|
||||
if (!_simulationOwner.isNull()) {
|
||||
// someone else really did own it
|
||||
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
|
||||
somethingChanged = true;
|
||||
_simulationOwner.clearCurrentOwner();
|
||||
}
|
||||
}
|
||||
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
|
||||
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,
|
||||
|
|
|
@ -353,13 +353,20 @@ void AssetClient::handleAssetGetReply(QSharedPointer<ReceivedMessage> message, S
|
|||
connect(message.data(), &ReceivedMessage::progress, this, [this, weakNode, messageID, length](qint64 size) {
|
||||
handleProgressCallback(weakNode, messageID, size, length);
|
||||
});
|
||||
connect(message.data(), &ReceivedMessage::completed, this, [this, weakNode, messageID]() {
|
||||
handleCompleteCallback(weakNode, messageID);
|
||||
connect(message.data(), &ReceivedMessage::completed, this, [this, weakNode, messageID, length]() {
|
||||
handleCompleteCallback(weakNode, messageID, length);
|
||||
});
|
||||
|
||||
if (message->isComplete()) {
|
||||
disconnect(message.data(), nullptr, this, nullptr);
|
||||
callbacks.completeCallback(true, error, message->readAll());
|
||||
|
||||
if (length != message->getBytesLeftToRead()) {
|
||||
callbacks.completeCallback(false, error, QByteArray());
|
||||
} else {
|
||||
callbacks.completeCallback(true, error, message->readAll());
|
||||
}
|
||||
|
||||
|
||||
messageCallbackMap.erase(requestIt);
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +398,7 @@ void AssetClient::handleProgressCallback(const QWeakPointer<Node>& node, Message
|
|||
callbacks.progressCallback(size, length);
|
||||
}
|
||||
|
||||
void AssetClient::handleCompleteCallback(const QWeakPointer<Node>& node, MessageID messageID) {
|
||||
void AssetClient::handleCompleteCallback(const QWeakPointer<Node>& node, MessageID messageID, DataOffset length) {
|
||||
auto senderNode = node.toStrongRef();
|
||||
|
||||
if (!senderNode) {
|
||||
|
@ -424,8 +431,7 @@ void AssetClient::handleCompleteCallback(const QWeakPointer<Node>& node, Message
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (message->failed()) {
|
||||
if (message->failed() || length != message->getBytesLeftToRead()) {
|
||||
callbacks.completeCallback(false, AssetServerError::NoError, QByteArray());
|
||||
} else {
|
||||
callbacks.completeCallback(true, AssetServerError::NoError, message->readAll());
|
||||
|
|
|
@ -93,7 +93,7 @@ private:
|
|||
bool cancelUploadAssetRequest(MessageID id);
|
||||
|
||||
void handleProgressCallback(const QWeakPointer<Node>& node, MessageID messageID, qint64 size, DataOffset length);
|
||||
void handleCompleteCallback(const QWeakPointer<Node>& node, MessageID messageID);
|
||||
void handleCompleteCallback(const QWeakPointer<Node>& node, MessageID messageID, DataOffset length);
|
||||
|
||||
void forceFailureOfPendingRequests(SharedNodePointer node);
|
||||
|
||||
|
|
|
@ -104,12 +104,7 @@ void AssetRequest::start() {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
if (_byteRange.isSet()) {
|
||||
// we had a byte range, the size of the data does not match what we expect, so we return an error
|
||||
if (data.size() != _byteRange.size()) {
|
||||
_error = SizeVerificationFailed;
|
||||
}
|
||||
} else if (hashData(data).toHex() != _hash) {
|
||||
if (!_byteRange.isSet() && hashData(data).toHex() != _hash) {
|
||||
// the hash of the received data does not match what we expect, so we return an error
|
||||
_error = HashVerificationFailed;
|
||||
}
|
||||
|
|
|
@ -23,14 +23,16 @@ const uint16_t ObjectActionTractor::tractorVersion = 1;
|
|||
|
||||
ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity),
|
||||
_positionalTarget(glm::vec3(0.0f)),
|
||||
_desiredPositionalTarget(glm::vec3(0.0f)),
|
||||
_positionalTarget(0.0f),
|
||||
_desiredPositionalTarget(0.0f),
|
||||
_linearTimeScale(FLT_MAX),
|
||||
_positionalTargetSet(true),
|
||||
_rotationalTarget(glm::quat()),
|
||||
_desiredRotationalTarget(glm::quat()),
|
||||
_positionalTargetSet(false),
|
||||
_rotationalTarget(),
|
||||
_desiredRotationalTarget(),
|
||||
_angularTimeScale(FLT_MAX),
|
||||
_rotationalTargetSet(true) {
|
||||
_rotationalTargetSet(true),
|
||||
_linearVelocityTarget(0.0f)
|
||||
{
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor";
|
||||
#endif
|
||||
|
@ -77,7 +79,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
|||
|
||||
glm::quat rotation;
|
||||
glm::vec3 position;
|
||||
glm::vec3 linearVelocity;
|
||||
glm::vec3 angularVelocity;
|
||||
|
||||
bool linearValid = false;
|
||||
|
@ -117,7 +118,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
|||
linearValid = true;
|
||||
linearTractorCount++;
|
||||
position += positionForAction;
|
||||
linearVelocity += linearVelocityForAction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,9 +126,18 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
|||
withWriteLock([&]{
|
||||
if (linearValid && linearTractorCount > 0) {
|
||||
position /= linearTractorCount;
|
||||
linearVelocity /= linearTractorCount;
|
||||
if (_positionalTargetSet) {
|
||||
_lastPositionTarget = _positionalTarget;
|
||||
} else {
|
||||
_lastPositionTarget = position;
|
||||
}
|
||||
_positionalTarget = position;
|
||||
_linearVelocityTarget = linearVelocity;
|
||||
if (deltaTimeStep > EPSILON) {
|
||||
// blend the new velocity with the old (low-pass filter)
|
||||
glm::vec3 newVelocity = (1.0f / deltaTimeStep) * (position - _lastPositionTarget);
|
||||
const float blend = 0.25f;
|
||||
_linearVelocityTarget = (1.0f - blend) * _linearVelocityTarget + blend * newVelocity;
|
||||
}
|
||||
_positionalTargetSet = true;
|
||||
_active = true;
|
||||
}
|
||||
|
@ -169,19 +178,19 @@ void ObjectActionTractor::updateActionWorker(btScalar deltaTimeStep) {
|
|||
}
|
||||
|
||||
if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) {
|
||||
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
|
||||
btVector3 offsetVelocity(0.0f, 0.0f, 0.0f);
|
||||
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
|
||||
float offsetLength = offset.length();
|
||||
if (offsetLength > FLT_EPSILON) {
|
||||
float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED);
|
||||
targetVelocity = (-speed / offsetLength) * offset;
|
||||
offsetVelocity = (-speed / offsetLength) * offset;
|
||||
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
||||
forceBodyNonStatic();
|
||||
rigidBody->activate();
|
||||
}
|
||||
}
|
||||
// this action is aggresively critically damped and defeats the current velocity
|
||||
rigidBody->setLinearVelocity(targetVelocity);
|
||||
rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget) + offsetVelocity);
|
||||
}
|
||||
|
||||
if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) {
|
||||
|
|
|
@ -36,6 +36,7 @@ protected:
|
|||
|
||||
glm::vec3 _positionalTarget;
|
||||
glm::vec3 _desiredPositionalTarget;
|
||||
glm::vec3 _lastPositionTarget;
|
||||
float _linearTimeScale;
|
||||
bool _positionalTargetSet;
|
||||
|
||||
|
|
Loading…
Reference in a new issue