mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge branch '20805' into 20809
This commit is contained in:
commit
7ee1edac3a
43 changed files with 375 additions and 114 deletions
|
@ -564,7 +564,7 @@ function MyController(hand) {
|
|||
"additiveBlending": 0,
|
||||
"textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png"
|
||||
}
|
||||
|
||||
|
||||
this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject);
|
||||
};
|
||||
|
||||
|
@ -1588,7 +1588,9 @@ function MyController(hand) {
|
|||
|
||||
ids.forEach(function(id) {
|
||||
var props = Entities.getEntityProperties(id, ["boundingBox", "name"]);
|
||||
if (props.name === 'pointer') {
|
||||
if (!props ||
|
||||
!props.boundingBox ||
|
||||
props.name === 'pointer') {
|
||||
return;
|
||||
}
|
||||
var entityMinPoint = props.boundingBox.brn;
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
function createEmitNumberPropertyUpdateFunction(propertyName) {
|
||||
return function() {
|
||||
EventBridge.emitWebEvent(
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + Number(this.value.toFixed(4)) + '}}'
|
||||
'{ "type":"update", "properties":{"' + propertyName + '":' + parseFloat(this.value).toFixed(4) + '}}'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,11 +32,9 @@ ParticleExplorerTool = function() {
|
|||
|
||||
that.destroyWebView = function() {
|
||||
if (!that.webView) {
|
||||
print("EBL CAN'ZT CLOSE WEB VIEW- IT DOESNT EXISTS!")
|
||||
return;
|
||||
}
|
||||
|
||||
print("EBL CLOSING WEB VIEW")
|
||||
that.webView.close();
|
||||
that.webView = null;
|
||||
that.activeParticleEntity = 0;
|
||||
|
|
|
@ -132,7 +132,7 @@ TableView {
|
|||
// FIXME: Put reload item in tableModel passed in from RunningScripts.
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: "a"
|
||||
text: hifi.glyphs.reloadSmall
|
||||
color: parent.color
|
||||
anchors {
|
||||
top: parent.top
|
||||
|
@ -148,7 +148,7 @@ TableView {
|
|||
// FIXME: Put stop item in tableModel passed in from RunningScripts.
|
||||
HiFiGlyphs {
|
||||
id: stopButton
|
||||
text: "C"
|
||||
text: hifi.glyphs.closeSmall
|
||||
color: parent.color
|
||||
anchors {
|
||||
top: parent.top
|
||||
|
|
|
@ -22,7 +22,7 @@ TextField {
|
|||
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
font.family: firaSansSemiBold.name
|
||||
font.pointSize: hifi.fontSizes.textFieldInput
|
||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||
height: implicitHeight + 4 // Make surrounding box higher so that highlight is vertically centered.
|
||||
placeholderText: textField.label // Instead of separate label (see below).
|
||||
|
||||
|
|
|
@ -54,6 +54,18 @@ TreeView {
|
|||
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
|
||||
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
||||
|
||||
branchDelegate: HiFiGlyphs {
|
||||
text: styleData.isExpanded ? hifi.glyphs.disclosureCollapse : hifi.glyphs.disclosureExpand
|
||||
size: hifi.fontSizes.tableText * 2.5 // tableText is in points; proportionately scale to pixels
|
||||
color: colorScheme == hifi.colorSchemes.light
|
||||
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
|
||||
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: hifi.dimensions.tablePadding / 2
|
||||
}
|
||||
}
|
||||
|
||||
handle: Item {
|
||||
id: scrollbarHandle
|
||||
implicitWidth: 6
|
||||
|
|
|
@ -18,12 +18,19 @@ import "../js/Utils.js" as Utils
|
|||
// This is our primary 'desktop' object to which all VR dialogs and windows are childed.
|
||||
FocusScope {
|
||||
id: desktop
|
||||
anchors.fill: parent;
|
||||
objectName: "desktop"
|
||||
|
||||
// Allow the scale of the desktop to be changed without screwing up the size relative to the parent.
|
||||
height: parent.height / scale
|
||||
width: parent.width / scale
|
||||
|
||||
onHeightChanged: d.repositionAll();
|
||||
onWidthChanged: d.repositionAll();
|
||||
|
||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||
// when they're opened.
|
||||
signal showDesktop();
|
||||
|
||||
// Allows QML/JS to find the desktop through the parent chain
|
||||
property bool desktopRoot: true
|
||||
|
||||
|
@ -225,6 +232,8 @@ FocusScope {
|
|||
}
|
||||
|
||||
reposition(targetWindow);
|
||||
|
||||
showDesktop();
|
||||
}
|
||||
|
||||
function reposition(item) {
|
||||
|
@ -322,5 +331,5 @@ FocusScope {
|
|||
enabled: DebugQML
|
||||
onTriggered: focusDebugger.visible = !focusDebugger.visible
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Window {
|
|||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
x: 40; y: 40
|
||||
implicitWidth: 384; implicitHeight: 650
|
||||
implicitWidth: 384; implicitHeight: 640
|
||||
minSize: Qt.vector2d(200, 300)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: anonymousProRegular; source: "../../fonts/AnonymousPro-Regular.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: anonymousProRegular.name
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: firaSansSemiBold.name
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: hiFiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
|
||||
property int size: 32
|
||||
font.pixelSize: size // Size this font in pixels because it's UI widgets.
|
||||
font.pixelSize: size
|
||||
width: size
|
||||
height: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
|
@ -16,6 +16,7 @@ Item {
|
|||
readonly property alias colorSchemes: colorSchemes
|
||||
readonly property alias dimensions: dimensions
|
||||
readonly property alias fontSizes: fontSizes
|
||||
readonly property alias glyphs: glyphs
|
||||
readonly property alias buttons: buttons
|
||||
readonly property alias effects: effects
|
||||
|
||||
|
@ -83,22 +84,35 @@ Item {
|
|||
}
|
||||
|
||||
Item {
|
||||
id: fontSizes
|
||||
readonly property real overlayTitle: dimensions.largeScreen? 16 : 12
|
||||
readonly property real tabName: dimensions.largeScreen? 11 : 9
|
||||
readonly property real sectionName: dimensions.largeScreen? 11 : 9
|
||||
readonly property real inputLabel: dimensions.largeScreen? 13.5 : 9
|
||||
readonly property real textFieldInput: dimensions.largeScreen? 13.5 : 11
|
||||
readonly property real tableText: dimensions.largeScreen? 13.5 : 11
|
||||
readonly property real buttonLabel: dimensions.largeScreen? 12 : 8
|
||||
readonly property real iconButton: dimensions.largeScreen? 12: 8
|
||||
readonly property real listItem: dimensions.largeScreen? 13.5 : 9
|
||||
readonly property real tabularData: dimensions.largeScreen? 11 : 9
|
||||
readonly property real logs: dimensions.largeScreen? 15 : 10
|
||||
readonly property real code: dimensions.largeScreen? 15 : 10
|
||||
readonly property real rootMenu: dimensions.largeScreen? 13.5 : 9
|
||||
readonly property real menuItem: dimensions.largeScreen? 13.5 : 9
|
||||
readonly property real shortcutText: dimensions.largeScreen? 12 : 8
|
||||
id: fontSizes // In pixels
|
||||
readonly property real overlayTitle: dimensions.largeScreen? 18 : 14
|
||||
readonly property real tabName: dimensions.largeScreen? 12 : 10
|
||||
readonly property real sectionName: dimensions.largeScreen? 12 : 10
|
||||
readonly property real inputLabel: dimensions.largeScreen? 14 : 10
|
||||
readonly property real textFieldInput: dimensions.largeScreen? 15 : 12
|
||||
readonly property real tableText: dimensions.largeScreen? 15 : 12
|
||||
readonly property real buttonLabel: dimensions.largeScreen? 13 : 9
|
||||
readonly property real iconButton: dimensions.largeScreen? 13 : 9
|
||||
readonly property real listItem: dimensions.largeScreen? 15 : 11
|
||||
readonly property real tabularData: dimensions.largeScreen? 15 : 11
|
||||
readonly property real logs: dimensions.largeScreen? 16 : 12
|
||||
readonly property real code: dimensions.largeScreen? 16 : 12
|
||||
readonly property real rootMenu: dimensions.largeScreen? 15 : 11
|
||||
readonly property real menuItem: dimensions.largeScreen? 15 : 11
|
||||
readonly property real shortcutText: dimensions.largeScreen? 13 : 9
|
||||
}
|
||||
|
||||
Item {
|
||||
id: glyphs
|
||||
readonly property string close: "w"
|
||||
readonly property string closeInverted: "x"
|
||||
readonly property string closeSmall: "C"
|
||||
readonly property string disclosureCollapse: "Z"
|
||||
readonly property string disclosureExpand: "B"
|
||||
readonly property string pin: "y"
|
||||
readonly property string pinInverted: "z"
|
||||
readonly property string reloadSmall: "a"
|
||||
readonly property string resizeHandle: "A"
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: ralewayBold; source: "../../fonts/Raleway-Bold.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: ralewayBold.name
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: ralewayLight; source: "../../fonts/Raleway-Light.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: ralewayLight.name
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: ralewayRegular.name
|
||||
|
|
|
@ -16,7 +16,7 @@ Text {
|
|||
id: root
|
||||
FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; }
|
||||
property real size: 32
|
||||
font.pointSize: size
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
font.family: ralewaySemibold.name
|
||||
|
|
|
@ -53,7 +53,7 @@ Frame {
|
|||
HiFiGlyphs {
|
||||
// "Pin" button
|
||||
visible: false
|
||||
text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? "z" : "y"
|
||||
text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? hifi.glyphs.pinInverted : hifi.glyphs.pin
|
||||
color: pinClickArea.containsMouse && !pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: iconSize
|
||||
MouseArea {
|
||||
|
@ -68,7 +68,7 @@ Frame {
|
|||
HiFiGlyphs {
|
||||
// "Close" button
|
||||
visible: window ? window.closable : false
|
||||
text: closeClickArea.containsPress ? "x" : "w"
|
||||
text: closeClickArea.containsPress ? hifi.glyphs.closeInverted : hifi.glyphs.close
|
||||
color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: iconSize
|
||||
MouseArea {
|
||||
|
|
|
@ -125,7 +125,7 @@ Item {
|
|||
visible: sizeDrag.enabled
|
||||
x: -11 // Move a little to visually align
|
||||
y: -4 // ""
|
||||
text: "A"
|
||||
text: hifi.glyphs.resizeHandle
|
||||
size: iconSize + 10
|
||||
color: sizeDrag.containsMouse || sizeDrag.pressed ? hifi.colors.white : hifi.colors.white50
|
||||
}
|
||||
|
|
|
@ -1198,7 +1198,8 @@ void Application::initializeUi() {
|
|||
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
||||
// support the window management and scripting proxies for VR use
|
||||
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
|
||||
|
||||
connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop);
|
||||
|
||||
// FIXME either expose so that dialogs can set this themselves or
|
||||
// do better detection in the offscreen UI of what has focus
|
||||
offscreenUi->setNavigationFocused(false);
|
||||
|
@ -3772,8 +3773,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
// The pending changes collecting the changes here
|
||||
render::PendingChanges pendingChanges;
|
||||
|
||||
// FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities
|
||||
// Background rendering decision
|
||||
if (BackgroundRenderData::_item == 0) {
|
||||
if (!render::Item::isValidID(BackgroundRenderData::_item)) {
|
||||
auto backgroundRenderData = make_shared<BackgroundRenderData>();
|
||||
auto backgroundRenderPayload = make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
|
||||
BackgroundRenderData::_item = _main3DScene->allocateID();
|
||||
|
@ -3798,8 +3800,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: Move this out of here!, WorldBox should be driven by the entity content just like the other entities
|
||||
// Make sure the WorldBox is in the scene
|
||||
if (WorldBoxRenderData::_item == 0) {
|
||||
if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||
auto worldBoxRenderData = make_shared<WorldBoxRenderData>();
|
||||
auto worldBoxRenderPayload = make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||
|
||||
|
@ -5128,3 +5131,9 @@ void Application::readArgumentsFromLocalSocket() {
|
|||
qApp->openUrl(QString::fromUtf8(message));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::showDesktop() {
|
||||
if (!_overlayConductor.getEnabled()) {
|
||||
_overlayConductor.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,7 @@ public slots:
|
|||
void runTests();
|
||||
|
||||
private slots:
|
||||
void showDesktop();
|
||||
void clearDomainOctreeDetails();
|
||||
void idle(uint64_t now);
|
||||
void aboutToQuit();
|
||||
|
|
|
@ -315,6 +315,7 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene>
|
|||
|
||||
void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_renderItemID);
|
||||
render::Item::clearID(_renderItemID);
|
||||
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||
getHead()->getFaceModel().removeFromScene(scene, pendingChanges);
|
||||
for (auto& attachmentModel : _attachmentModels) {
|
||||
|
@ -323,7 +324,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
|||
}
|
||||
|
||||
void Avatar::updateRenderItem(render::PendingChanges& pendingChanges) {
|
||||
if (_renderItemID != render::Item::INVALID_ITEM_ID) {
|
||||
if (render::Item::isValidID(_renderItemID)) {
|
||||
pendingChanges.updateItem<render::Payload<AvatarData>>(_renderItemID, [](render::Payload<AvatarData>& p) {});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,6 +229,6 @@ bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene
|
|||
|
||||
void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_renderItemID);
|
||||
_renderItemID = render::Item::INVALID_ITEM_ID;
|
||||
render::Item::clearID(_renderItemID);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ void Overlays::cleanupOverlaysToDelete() {
|
|||
Overlay::Pointer overlay = _overlaysToDelete.takeLast();
|
||||
|
||||
auto itemID = overlay->getRenderItemID();
|
||||
if (itemID != render::Item::INVALID_ITEM_ID) {
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
overlay->removeFromScene(overlay, scene, pendingChanges);
|
||||
}
|
||||
} while (!_overlaysToDelete.isEmpty());
|
||||
|
@ -241,7 +241,7 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
|||
render::ItemKey itemKey = render::payloadGetKey(thisOverlay);
|
||||
if (itemKey != oldItemKey) {
|
||||
auto itemID = thisOverlay->getRenderItemID();
|
||||
if (itemID != render::Item::INVALID_ITEM_ID) {
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::PendingChanges pendingChanges;
|
||||
pendingChanges.resortItem(itemID, oldItemKey, itemKey);
|
||||
|
|
|
@ -104,7 +104,9 @@ void AudioInjector::restart() {
|
|||
|
||||
// reset state to start sending from beginning again
|
||||
_nextFrame = 0;
|
||||
_frameTimer->invalidate();
|
||||
if (_frameTimer) {
|
||||
_frameTimer->invalidate();
|
||||
}
|
||||
_hasSentFirstFrame = false;
|
||||
|
||||
// check our state to decide if we need extra handling for the restart request
|
||||
|
@ -122,7 +124,9 @@ void AudioInjector::restart() {
|
|||
injectLocally();
|
||||
} else {
|
||||
// wake the AudioInjectorManager back up if it's stuck waiting
|
||||
injectorManager->restartFinishedInjector(this);
|
||||
if (!injectorManager->restartFinishedInjector(this)) {
|
||||
_state = State::Finished; // we're not playing, so reset the state used by isPlaying.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,15 @@ void AudioInjectorManager::run() {
|
|||
|
||||
static const int MAX_INJECTORS_PER_THREAD = 40; // calculated based on AudioInjector time to send frame, with sufficient padding
|
||||
|
||||
bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a lock.
|
||||
if (_injectors.size() >= MAX_INJECTORS_PER_THREAD) {
|
||||
qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of"
|
||||
<< MAX_INJECTORS_PER_THREAD << "current audio injectors.";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioInjectorManager::threadInjector(AudioInjector* injector) {
|
||||
if (_shouldStop) {
|
||||
qDebug() << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down.";
|
||||
|
@ -138,8 +147,9 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) {
|
|||
// guard the injectors vector with a mutex
|
||||
Lock lock(_injectorsMutex);
|
||||
|
||||
// check if we'll be able to thread this injector (do we have < max concurrent injectors)
|
||||
if (_injectors.size() < MAX_INJECTORS_PER_THREAD) {
|
||||
if (wouldExceedLimits()) {
|
||||
return false;
|
||||
} else {
|
||||
if (!_thread) {
|
||||
createThread();
|
||||
}
|
||||
|
@ -156,23 +166,22 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) {
|
|||
_injectorReady.notify_one();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// unable to thread this injector, at the max
|
||||
qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of"
|
||||
<< MAX_INJECTORS_PER_THREAD << "current audio injectors.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) {
|
||||
bool AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) {
|
||||
if (!_shouldStop) {
|
||||
// guard the injectors vector with a mutex
|
||||
Lock lock(_injectorsMutex);
|
||||
|
||||
if (wouldExceedLimits()) {
|
||||
return false;
|
||||
}
|
||||
// add the injector to the queue with a send timestamp of now
|
||||
_injectors.emplace(usecTimestampNow(), InjectorQPointer { injector });
|
||||
|
||||
// notify our wait condition so we can inject two frames for this injector immediately
|
||||
_injectorReady.notify_one();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,9 @@ private:
|
|||
using Lock = std::unique_lock<Mutex>;
|
||||
|
||||
bool threadInjector(AudioInjector* injector);
|
||||
void restartFinishedInjector(AudioInjector* injector);
|
||||
bool restartFinishedInjector(AudioInjector* injector);
|
||||
void notifyInjectorReadyCondition() { _injectorReady.notify_one(); }
|
||||
bool wouldExceedLimits();
|
||||
|
||||
AudioInjectorManager() {};
|
||||
AudioInjectorManager(const AudioInjectorManager&) = delete;
|
||||
|
|
|
@ -66,10 +66,11 @@ public:
|
|||
|
||||
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myItem);
|
||||
render::Item::clearID(_myItem);
|
||||
}
|
||||
|
||||
void notifyChanged() {
|
||||
if (_myItem == render::Item::INVALID_ITEM_ID) {
|
||||
if (!render::Item::isValidID(_myItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -251,6 +251,7 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
|
|||
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myMetaItem);
|
||||
render::Item::clearID(_myMetaItem);
|
||||
if (_model) {
|
||||
_model->removeFromScene(scene, pendingChanges);
|
||||
}
|
||||
|
|
|
@ -179,6 +179,7 @@ void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self,
|
|||
render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_renderItemId);
|
||||
_scene = nullptr;
|
||||
render::Item::clearID(_renderItemId);
|
||||
};
|
||||
|
||||
void RenderableParticleEffectEntityItem::update(const quint64& now) {
|
||||
|
@ -199,7 +200,8 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) {
|
|||
}
|
||||
|
||||
void RenderableParticleEffectEntityItem::updateRenderItem() {
|
||||
if (!_scene) {
|
||||
// this 2 tests are synonyms for this class, but we would like to get rid of the _scene pointer ultimately
|
||||
if (!_scene || !render::Item::isValidID(_renderItemId)) {
|
||||
return;
|
||||
}
|
||||
if (!getVisible()) {
|
||||
|
@ -312,7 +314,7 @@ void RenderableParticleEffectEntityItem::createPipelines() {
|
|||
}
|
||||
|
||||
void RenderableParticleEffectEntityItem::notifyBoundChanged() {
|
||||
if (_renderItemId == render::Item::INVALID_ITEM_ID) {
|
||||
if (!render::Item::isValidID(_renderItemId)) {
|
||||
return;
|
||||
}
|
||||
render::PendingChanges pendingChanges;
|
||||
|
|
|
@ -572,6 +572,7 @@ void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self,
|
|||
std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myItem);
|
||||
render::Item::clearID(_myItem);
|
||||
}
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -230,6 +230,7 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt
|
|||
void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myMetaItem);
|
||||
render::Item::clearID(_myMetaItem);
|
||||
if (_model) {
|
||||
_model->removeFromScene(scene, pendingChanges);
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shar
|
|||
|
||||
|
||||
void RenderableZoneEntityItem::notifyBoundChanged() {
|
||||
if (_myMetaItem == render::Item::INVALID_ITEM_ID) {
|
||||
if (!render::Item::isValidID(_myMetaItem)) {
|
||||
return;
|
||||
}
|
||||
render::PendingChanges pendingChanges;
|
||||
|
|
|
@ -21,6 +21,17 @@
|
|||
class NLPacket : public udt::Packet {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Packet Type | Packet Version |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Node UUID | Hash (only if verified) | Optional (only if sourced)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// NLPacket Header Format
|
||||
|
||||
// this is used by the Octree classes - must be known at compile time
|
||||
static const int MAX_PACKET_HEADER_SIZE =
|
||||
sizeof(udt::Packet::SequenceNumberAndBitField) + sizeof(udt::Packet::MessageNumberAndBitField) +
|
||||
|
|
|
@ -26,10 +26,65 @@ namespace udt {
|
|||
static const int UDP_SEND_BUFFER_SIZE_BYTES = 1048576;
|
||||
static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576;
|
||||
static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000;
|
||||
static const int SEQUENCE_NUMBER_BITS = sizeof(SequenceNumber) * 8;
|
||||
static const int MESSAGE_LINE_NUMBER_BITS = 32;
|
||||
static const int MESSAGE_NUMBER_BITS = 30;
|
||||
static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 1);
|
||||
|
||||
|
||||
// Header constants
|
||||
|
||||
// Bit sizes (in order)
|
||||
static const int CONTROL_BIT_SIZE = 1;
|
||||
static const int RELIABILITY_BIT_SIZE = 1;
|
||||
static const int MESSAGE_BIT_SIZE = 1;
|
||||
static const int OBFUSCATION_LEVEL_SIZE = 2;
|
||||
static const int SEQUENCE_NUMBER_SIZE= 27;
|
||||
|
||||
static const int PACKET_POSITION_SIZE = 2;
|
||||
static const int MESSAGE_NUMBER_SIZE = 30;
|
||||
|
||||
static const int MESSAGE_PART_NUMBER_SIZE = 32;
|
||||
|
||||
// Offsets
|
||||
static const int SEQUENCE_NUMBER_OFFSET = 0;
|
||||
static const int OBFUSCATION_LEVEL_OFFSET = SEQUENCE_NUMBER_OFFSET + SEQUENCE_NUMBER_SIZE;
|
||||
static const int MESSAGE_BIT_OFFSET = OBFUSCATION_LEVEL_OFFSET + OBFUSCATION_LEVEL_SIZE;
|
||||
static const int RELIABILITY_BIT_OFFSET = MESSAGE_BIT_OFFSET + MESSAGE_BIT_SIZE;
|
||||
static const int CONTROL_BIT_OFFSET = RELIABILITY_BIT_OFFSET + RELIABILITY_BIT_SIZE;
|
||||
|
||||
static const int MESSAGE_NUMBER_OFFSET = 0;
|
||||
static const int PACKET_POSITION_OFFSET = MESSAGE_NUMBER_OFFSET + MESSAGE_NUMBER_SIZE;
|
||||
|
||||
static const int MESSAGE_PART_NUMBER_OFFSET = 0;
|
||||
|
||||
// Masks
|
||||
static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << CONTROL_BIT_OFFSET;
|
||||
static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << RELIABILITY_BIT_OFFSET;
|
||||
static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << MESSAGE_BIT_OFFSET;
|
||||
static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(3) << OBFUSCATION_LEVEL_OFFSET;
|
||||
static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK;
|
||||
static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK;
|
||||
|
||||
static const uint32_t PACKET_POSITION_MASK = uint32_t(3) << PACKET_POSITION_OFFSET;
|
||||
static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK;
|
||||
|
||||
static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0);
|
||||
|
||||
|
||||
// Static checks
|
||||
static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE +
|
||||
OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect");
|
||||
static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect");
|
||||
static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect");
|
||||
|
||||
static_assert(CONTROL_BIT_MASK == 0x80000000, "CONTROL_BIT_MASK incorrect");
|
||||
static_assert(RELIABILITY_BIT_MASK == 0x40000000, "RELIABILITY_BIT_MASK incorrect");
|
||||
static_assert(MESSAGE_BIT_MASK == 0x20000000, "MESSAGE_BIT_MASK incorrect");
|
||||
static_assert(OBFUSCATION_LEVEL_MASK == 0x18000000, "OBFUSCATION_LEVEL_MASK incorrect");
|
||||
static_assert(BIT_FIELD_MASK == 0xF8000000, "BIT_FIELD_MASK incorrect");
|
||||
static_assert(SEQUENCE_NUMBER_MASK == 0x07FFFFFF, "SEQUENCE_NUMBER_MASK incorrect");
|
||||
|
||||
static_assert(PACKET_POSITION_MASK == 0xC0000000, "PACKET_POSITION_MASK incorrect");
|
||||
static_assert(MESSAGE_NUMBER_MASK == 0x3FFFFFFF, "MESSAGE_NUMBER_MASK incorrect");
|
||||
|
||||
static_assert(MESSAGE_PART_NUMBER_MASK == 0xFFFFFFFF, "MESSAGE_PART_NUMBER_MASK incorrect");
|
||||
}
|
||||
|
||||
#endif // hifi_udt_Constants_h
|
||||
|
|
|
@ -11,10 +11,35 @@
|
|||
|
||||
#include "Packet.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <LogHandler.h>
|
||||
|
||||
using namespace udt;
|
||||
|
||||
static int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*");
|
||||
|
||||
using Key = uint64_t;
|
||||
static const std::array<Key, 4> KEYS {{
|
||||
0x0,
|
||||
0x6362726973736574,
|
||||
0x7362697261726461,
|
||||
0x72687566666d616e,
|
||||
}};
|
||||
|
||||
void xorHelper(char* start, int size, Key key) {
|
||||
const auto end = start + size;
|
||||
|
||||
auto p = start;
|
||||
for (; p + sizeof(Key) < end; p += sizeof(Key)) {
|
||||
*reinterpret_cast<Key*>(p) ^= key;
|
||||
}
|
||||
|
||||
for (int i = 0; p < end; ++p || ++i) {
|
||||
*p ^= *(reinterpret_cast<const char*>(&key) + i);
|
||||
}
|
||||
}
|
||||
|
||||
int Packet::localHeaderSize(bool isPartOfMessage) {
|
||||
return sizeof(Packet::SequenceNumberAndBitField) +
|
||||
(isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);
|
||||
|
@ -69,44 +94,48 @@ Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& se
|
|||
readHeader();
|
||||
|
||||
adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0);
|
||||
|
||||
if (getObfuscationLevel() != Packet::NoObfuscation) {
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
QString debugString = "Unobfuscating packet %1 with level %2";
|
||||
debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()),
|
||||
QString::number(getObfuscationLevel()));
|
||||
|
||||
if (isPartOfMessage()) {
|
||||
debugString += "\n";
|
||||
debugString += " Message Number: %1, Part Number: %2.";
|
||||
debugString = debugString.arg(QString::number(getMessageNumber()),
|
||||
QString::number(getMessagePartNumber()));
|
||||
}
|
||||
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*");
|
||||
qDebug() << qPrintable(debugString);
|
||||
#endif
|
||||
|
||||
obfuscate(NoObfuscation); // Undo obfuscation
|
||||
}
|
||||
}
|
||||
|
||||
Packet::Packet(const Packet& other) :
|
||||
BasePacket(other)
|
||||
{
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
Packet::Packet(const Packet& other) : BasePacket(other) {
|
||||
copyMembers(other);
|
||||
}
|
||||
|
||||
Packet& Packet::operator=(const Packet& other) {
|
||||
BasePacket::operator=(other);
|
||||
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
|
||||
copyMembers(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet::Packet(Packet&& other) :
|
||||
BasePacket(std::move(other))
|
||||
{
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
Packet::Packet(Packet&& other) : BasePacket(std::move(other)) {
|
||||
copyMembers(other);
|
||||
}
|
||||
|
||||
Packet& Packet::operator=(Packet&& other) {
|
||||
BasePacket::operator=(std::move(other));
|
||||
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
|
||||
copyMembers(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -124,13 +153,27 @@ void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const {
|
|||
writeHeader();
|
||||
}
|
||||
|
||||
static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2);
|
||||
static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3);
|
||||
static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK;
|
||||
void Packet::obfuscate(ObfuscationLevel level) {
|
||||
auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one.
|
||||
if (obfuscationKey != 0) {
|
||||
xorHelper(getData() + localHeaderSize(isPartOfMessage()),
|
||||
getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey);
|
||||
|
||||
static const uint8_t PACKET_POSITION_OFFSET = 30;
|
||||
static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET;
|
||||
static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK;
|
||||
// Update members and header
|
||||
_obfuscationLevel = level;
|
||||
writeHeader();
|
||||
}
|
||||
}
|
||||
|
||||
void Packet::copyMembers(const Packet& other) {
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_obfuscationLevel = other._obfuscationLevel;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
_messagePartNumber = other._messagePartNumber;
|
||||
}
|
||||
|
||||
void Packet::readHeader() const {
|
||||
SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
|
@ -139,10 +182,12 @@ void Packet::readHeader() const {
|
|||
|
||||
_isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit
|
||||
_isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit
|
||||
_sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field
|
||||
_obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET);
|
||||
_sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field
|
||||
|
||||
if (_isPartOfMessage) {
|
||||
MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1;
|
||||
|
||||
_messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK;
|
||||
_packetPosition = static_cast<PacketPosition>(*messageNumberAndBitField >> PACKET_POSITION_OFFSET);
|
||||
|
||||
|
@ -163,6 +208,10 @@ void Packet::writeHeader() const {
|
|||
if (_isReliable) {
|
||||
*seqNumBitField |= RELIABILITY_BIT_MASK;
|
||||
}
|
||||
|
||||
if (_obfuscationLevel != NoObfuscation) {
|
||||
*seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET);
|
||||
}
|
||||
|
||||
if (_isPartOfMessage) {
|
||||
*seqNumBitField |= MESSAGE_BIT_MASK;
|
||||
|
|
|
@ -25,6 +25,25 @@ namespace udt {
|
|||
class Packet : public BasePacket {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Packet Header Format
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |C|R|M| O | Sequence Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | P | Message Number | Optional (only if M = 1)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Message Part Number | Optional (only if M = 1)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// C: Control bit
|
||||
// R: Reliable bit
|
||||
// M: Message bit
|
||||
// O: Obfuscation level
|
||||
// P: Position bits
|
||||
|
||||
|
||||
// NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field
|
||||
using SequenceNumberAndBitField = uint32_t;
|
||||
|
||||
|
@ -35,12 +54,20 @@ public:
|
|||
|
||||
// Use same size as MessageNumberAndBitField so we can use the enum with bitwise operations
|
||||
enum PacketPosition : MessageNumberAndBitField {
|
||||
ONLY = 0x0,
|
||||
FIRST = 0x2,
|
||||
MIDDLE = 0x3,
|
||||
LAST = 0x1
|
||||
ONLY = 0x0, // 00
|
||||
FIRST = 0x2, // 10
|
||||
MIDDLE = 0x3, // 11
|
||||
LAST = 0x1 // 01
|
||||
};
|
||||
|
||||
|
||||
// Use same size as SequenceNumberAndBitField so we can use the enum with bitwise operations
|
||||
enum ObfuscationLevel : SequenceNumberAndBitField {
|
||||
NoObfuscation = 0x0, // 00
|
||||
ObfuscationL1 = 0x1, // 01
|
||||
ObfuscationL2 = 0x2, // 10
|
||||
ObfuscationL3 = 0x3, // 11
|
||||
};
|
||||
|
||||
static std::unique_ptr<Packet> create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false);
|
||||
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
|
@ -56,7 +83,8 @@ public:
|
|||
|
||||
bool isPartOfMessage() const { return _isPartOfMessage; }
|
||||
bool isReliable() const { return _isReliable; }
|
||||
|
||||
|
||||
ObfuscationLevel getObfuscationLevel() const { return _obfuscationLevel; }
|
||||
SequenceNumber getSequenceNumber() const { return _sequenceNumber; }
|
||||
MessageNumber getMessageNumber() const { return _messageNumber; }
|
||||
PacketPosition getPacketPosition() const { return _packetPosition; }
|
||||
|
@ -64,6 +92,7 @@ public:
|
|||
|
||||
void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber);
|
||||
void writeSequenceNumber(SequenceNumber sequenceNumber) const;
|
||||
void obfuscate(ObfuscationLevel level);
|
||||
|
||||
protected:
|
||||
Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false);
|
||||
|
@ -76,6 +105,8 @@ protected:
|
|||
Packet& operator=(Packet&& other);
|
||||
|
||||
private:
|
||||
void copyMembers(const Packet& other);
|
||||
|
||||
// Header readers - these read data to member variables after pulling packet off wire
|
||||
void readHeader() const;
|
||||
void writeHeader() const;
|
||||
|
@ -83,6 +114,7 @@ private:
|
|||
// Simple holders to prevent multiple reading and bitwise ops
|
||||
mutable bool _isReliable { false };
|
||||
mutable bool _isPartOfMessage { false };
|
||||
mutable ObfuscationLevel _obfuscationLevel { NoObfuscation };
|
||||
mutable SequenceNumber _sequenceNumber { 0 };
|
||||
mutable MessageNumber _messageNumber { 0 };
|
||||
mutable PacketPosition _packetPosition { PacketPosition::ONLY };
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
using namespace udt;
|
||||
|
||||
MessageNumber PacketQueue::getNextMessageNumber() {
|
||||
static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_BITS;
|
||||
static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_SIZE;
|
||||
_currentMessageNumber = (_currentMessageNumber + 1) % MAX_MESSAGE_NUMBER;
|
||||
return _currentMessageNumber;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
@ -225,7 +226,9 @@ void SendQueue::sendNewPacketAndAddToSentList(std::unique_ptr<Packet> newPacket,
|
|||
{
|
||||
// Insert the packet we have just sent in the sent list
|
||||
QWriteLocker locker(&_sentLock);
|
||||
_sentPackets[newPacket->getSequenceNumber()].swap(newPacket);
|
||||
auto& entry = _sentPackets[newPacket->getSequenceNumber()];
|
||||
entry.first = 0; // No resend
|
||||
entry.second.swap(newPacket);
|
||||
}
|
||||
Q_ASSERT_X(!newPacket, "SendQueue::sendNewPacketAndAddToSentList()", "Overriden packet in sent list");
|
||||
|
||||
|
@ -354,14 +357,46 @@ bool SendQueue::maybeResendPacket() {
|
|||
auto it = _sentPackets.find(resendNumber);
|
||||
|
||||
if (it != _sentPackets.end()) {
|
||||
auto& entry = it->second;
|
||||
// we found the packet - grab it
|
||||
auto& resendPacket = *(it->second);
|
||||
|
||||
// send it off
|
||||
sendPacket(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
auto& resendPacket = *(entry.second);
|
||||
++entry.first; // Add 1 resend
|
||||
|
||||
Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4);
|
||||
|
||||
if (level != Packet::NoObfuscation) {
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
QString debugString = "Obfuscating packet %1 with level %2";
|
||||
debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()),
|
||||
QString::number(level));
|
||||
if (resendPacket.isPartOfMessage()) {
|
||||
debugString += "\n";
|
||||
debugString += " Message Number: %1, Part Number: %2.";
|
||||
debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()),
|
||||
QString::number(resendPacket.getMessagePartNumber()));
|
||||
}
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*");
|
||||
qCritical() << qPrintable(debugString);
|
||||
#endif
|
||||
|
||||
// Create copy of the packet
|
||||
auto packet = Packet::createCopy(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
|
||||
// Obfuscate packet
|
||||
packet->obfuscate(level);
|
||||
|
||||
// send it off
|
||||
sendPacket(*packet);
|
||||
} else {
|
||||
// send it off
|
||||
sendPacket(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
}
|
||||
|
||||
emit packetRetransmitted();
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ private:
|
|||
LossList _naks; // Sequence numbers of packets to resend
|
||||
|
||||
mutable QReadWriteLock _sentLock; // Protects the sent packet list
|
||||
std::unordered_map<SequenceNumber, std::unique_ptr<Packet>> _sentPackets; // Packets waiting for ACK.
|
||||
using PacketResendPair = std::pair<uint8_t, std::unique_ptr<Packet>>; // Number of resend + packet ptr
|
||||
std::unordered_map<SequenceNumber, PacketResendPair> _sentPackets; // Packets waiting for ACK.
|
||||
|
||||
std::mutex _handshakeMutex; // Protects the handshake ACK condition_variable
|
||||
std::atomic<bool> _hasReceivedHandshakeACK { false }; // flag for receipt of handshake ACK from client
|
||||
|
|
|
@ -24,9 +24,9 @@ public:
|
|||
using Type = int32_t;
|
||||
using UType = uint32_t;
|
||||
|
||||
// Values are for 29 bit SequenceNumber
|
||||
static const Type THRESHOLD = 0x0FFFFFFF; // threshold for comparing sequence numbers
|
||||
static const Type MAX = 0x1FFFFFFF; // maximum sequence number used in UDT
|
||||
// Values are for 27 bit SequenceNumber
|
||||
static const Type THRESHOLD = 0x03FFFFFF; // threshold for comparing sequence numbers
|
||||
static const Type MAX = 0x07FFFFFF; // maximum sequence number used in UDT
|
||||
|
||||
SequenceNumber() = default;
|
||||
SequenceNumber(const SequenceNumber& other) : _value(other._value) {}
|
||||
|
|
|
@ -277,7 +277,7 @@ void Socket::readPendingDatagrams() {
|
|||
if (packet->isReliable()) {
|
||||
// if this was a reliable packet then signal the matching connection with the sequence number
|
||||
auto& connection = findOrCreateConnection(senderSockAddr);
|
||||
|
||||
|
||||
if (!connection.processReceivedSequenceNumber(packet->getSequenceNumber(),
|
||||
packet->getDataSize(),
|
||||
packet->getPayloadSize())) {
|
||||
|
|
|
@ -217,6 +217,10 @@ public:
|
|||
static const ID INVALID_ITEM_ID = 0;
|
||||
static const ItemCell INVALID_CELL = -1;
|
||||
|
||||
// Convenient function to clear an ID or check it s valid
|
||||
static void clearID(ID& id) { id = INVALID_ITEM_ID; }
|
||||
static bool isValidID(const ID id) { return id != INVALID_ITEM_ID; }
|
||||
|
||||
// Bound is the AABBox fully containing this item
|
||||
typedef AABox Bound;
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ void OffscreenUi::create(QOpenGLContext* context) {
|
|||
}
|
||||
|
||||
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
emit showDesktop();
|
||||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
// First load?
|
||||
if (!item) {
|
||||
|
@ -127,6 +128,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<voi
|
|||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
// Already loaded?
|
||||
if (item) {
|
||||
emit showDesktop();
|
||||
item->setVisible(!item->isVisible());
|
||||
return;
|
||||
}
|
||||
|
@ -134,6 +136,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<voi
|
|||
load(url, f);
|
||||
item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
if (item && !item->isVisible()) {
|
||||
emit showDesktop();
|
||||
item->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
@ -439,6 +442,8 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
|||
new VrMenu(this);
|
||||
|
||||
new KeyboardFocusHack();
|
||||
|
||||
connect(_desktop, SIGNAL(showDesktop()), this, SLOT(showDesktop()));
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::getDesktop() {
|
||||
|
|
|
@ -106,6 +106,9 @@ public:
|
|||
// Compatibility with QInputDialog::getItem
|
||||
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||
|
||||
signals:
|
||||
void showDesktop();
|
||||
|
||||
private:
|
||||
QString fileDialog(const QVariantMap& properties);
|
||||
|
||||
|
|
Loading…
Reference in a new issue