diff --git a/.github/workflows/linux_server_build.yml b/.github/workflows/linux_server_build.yml index 1931726120..64f1529221 100644 --- a/.github/workflows/linux_server_build.yml +++ b/.github/workflows/linux_server_build.yml @@ -26,8 +26,8 @@ env: jobs: build: - # Only run master or tagged builds, or PRs if labeled as "server" - if: contains( github.event.pull_request.labels.*.name, 'server') || github.event_name != 'pull_request' + # Only run master or tagged builds, or PRs when labeled as "server" + if: github.event.label.name == 'server'|| github.event_name != 'pull_request' name: "${{matrix.os}}, ${{matrix.arch}}" strategy: matrix: @@ -93,12 +93,12 @@ jobs: runner: [self_hosted, type-cax41, image-arm-app-docker-ce] - os: fedora-40 - image: docker.io/overte/overte-server-build:0.1.4-fedora-39-amd64 + image: docker.io/overte/overte-server-build:0.1.4-fedora-40-amd64 arch: amd64 runner: [self_hosted, type-cx52, image-x86-app-docker-ce] - os: fedora-40 - image: docker.io/overte/overte-server-build:0.1.4-fedora-39-aarch64 + image: docker.io/overte/overte-server-build:0.1.4-fedora-40-aarch64 arch: aarch64 runner: [self_hosted, type-cax41, image-arm-app-docker-ce] @@ -132,6 +132,8 @@ jobs: echo "GIT_COMMIT_SHORT=`echo ${{ github.sha }} | cut -c1-7`" >> $GITHUB_ENV fi + echo "REFNAME=${{ github.ref_name }}" >> $GITHUB_ENV + echo "JOB_NAME=${{matrix.os}}, ${{matrix.arch}}" >> $GITHUB_ENV echo "CMAKE_BUILD_EXTRA=-- -j$(nproc)" >> $GITHUB_ENV @@ -184,7 +186,8 @@ jobs: echo "RELEASE_NUMBER=${{ github.run_number }}" >> $GITHUB_ENV else # tagged echo "DEBVERSION=${{ github.ref_name }}-$GIT_COMMIT_SHORT-${{ matrix.os }}" >> $GITHUB_ENV - echo "RPMVERSION=${{ github.ref_name }}.$GIT_COMMIT_SHORT" >> $GITHUB_ENV + # We remove all dash characters from RPM versions, because rpmbuild doesn't allow dashes in version numbers. + echo "RPMVERSION=${REFNAME//-}.$GIT_COMMIT_SHORT" >> $GITHUB_ENV fi if [ "${{ github.ref_type }}" == "tag" ]; then # tagged @@ -199,15 +202,13 @@ jobs: echo "BUILD_NUMBER=$GIT_COMMIT_SHORT" >> $GITHUB_ENV - if [ -z "$CMAKE_BACKTRACE_URL" ]; then - if [ "${{ github.ref_type }}" == "tag" ]; then - export CMAKE_BACKTRACE_URL="${{ secrets.SENTRY_MINIDUMP_ENDPOINT }}" - export CMAKE_BACKTRACE_TOKEN="${{ github.ref_name }}_${{ matrix.os }}_${{ github.sha }}" - else - # We're building a PR, default to the PR endpoint - export CMAKE_BACKTRACE_URL="https://o4504831972343808.ingest.sentry.io/api/4504832427950080/minidump/?sentry_key=f511de295975461b8f92a36f4a4a4f32" - export CMAKE_BACKTRACE_TOKEN="server_pr_${{ github.event.number }}_${{ github.sha }}" - fi + if [ "${{ github.ref_type }}" == "tag" ]; then + export CMAKE_BACKTRACE_URL="${{ secrets.SENTRY_MINIDUMP_ENDPOINT }}" + export CMAKE_BACKTRACE_TOKEN="${{ github.ref_name }}_${{ matrix.os }}_${{ github.sha }}" + else + # We're building a PR, default to the PR endpoint + export CMAKE_BACKTRACE_URL="https://o4504831972343808.ingest.sentry.io/api/4504832427950080/minidump/?sentry_key=f511de295975461b8f92a36f4a4a4f32" + export CMAKE_BACKTRACE_TOKEN="server_pr_${{ github.event.number }}_${{ github.sha }}" fi - name: Configure Build Environment 3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a1d98ebb0..de11f33c5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,14 +12,149 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), This project does **not** adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - + - +## [2024.07.1] 2023.07.12 + +### Fixes +- Fix more warnings (PR1007) +- Fix new debug build warning (PR1013) +- Fix RPM packaging (PR1025) +- Temporary fix for some script messages not being transmitted (PR1024) +- Fix unhandled std::bad_weak_ptr (PR1037) +- Fix long messages in Entity script log (PR1029) +- Allow events from VR keyboard to overlay UI (PR1046) +- Fix Fedora 40 server packages. (PR1057) +- Fix crash in setCrashReporterEnabled (PR1065) +- Fix mtoon issue on GLES (PR1055) +- Fix GHA building hundreds of servers (PR1071) +- Fix broken upload paths for RPM distributions. (PR1072) + +### Changes +- Text Entity Improvements (PR937) +- GitHub Action Runner auto-scaling (PR1021) +- Remove some external refrences (PR1026) +- Update from deprecated actions/checkout and actions/upload-artifact (PR1023) +- Update Ubuntu 20.04 amd64 Qt package (PR1032) +- Cut back on master builds. (PR1049) +- Increase default vertical FOV (PR1061) +- Always enable crash reporting. (PR1064) +- Update make-rpm-server to remove - characters. (PR1063) +- Update VCPKG on Windows, so it can find newer versions of Visual Studio. (PR1073) + +### Additions +- Add a script to more easily build Debian and RPM server packages. (PR1011) +- Add Fedora 40 servers (PR1010) +- GitHub Actions server release builds (PR1022) +- Wiggly lasers (PR1014) +- Create Windows release builds. (PR1048) + +### Removals +- Remove broken ccache macro (PR1018) +- Remove note about secure WebSockets not being supported. (PR1040) +- Remove RELEASE_NAME (PR1039) +- Remove hifiNeuron.dll (PR1075) +- Remove remnants of RELEASE_NAME. (PR1077) + + +## [2024.06.1] 2023.06.24 + +### Fixes +- Fix QNetworkRequest::FollowRedirectsAttribute deprecated warning (PR711) +- Fix luci (PR724) +- Fix setting external port and IP address for manual networking modes (PR746) +- particle billboarding is wrong in VR (PR747) +- Upgrade openexr (PR752) +- Fix OpenEXR on Windows (PR756) +- Upgrade Steamworks and fix for ninja build (PR755) +- Fixes for Oculus VR plugin (PR758) +- Fix Ninja builds with Crashpad enabled on Windows (PR765) +- Fix a bug in Entities.getEntityProperties (PR768) +- Fixed returnNothingOnEmptyPropertyFlags (PR770) +- ✨ "Update Existing Avatar" now properly updates the fst file (PR576) +- Fix the doppleganger position in the tutorial (PR781) +- Fix entity density not setting and not updating for motion states (PR819) +- Add keyboard modifiers to entity pointer events (PR815) +- 🐛 Fixed build on Windows (PR827) +- Fix recording API documentation not being built (PR829) +- Fix the display of Notifications (PR831) +- Fix prebuild.py code ordering to make --get-vcpkg-id and --get-vcpkg-path correctly in the repo root (PR836) +- Fixed avatar volume adjustment (PR841) +- Respect cull face during shadow pass (PR820) +- Fix Developer > UI > Show Overlays + Snap UI not hiding (PR823) +- Fixed blendshapes in gltf importer (PR840) +- Fix require behavior for modules (PR855) +- 🐛 Fixed avatar bounding box being inverted (PR866) +- Fix collisions on glTF avatars (PR867) +- Clean up GeometryCache and remove _glColor4f (PR845) +- Fix warnings as errors for MSVC (PR873) +- Fix invalid animation reference in assignment client (PR854) +- Fix previous commit for not loading textures on agent (PR893) +- conversionPenaltyScore should accumulate (PR935) +- Fix getEntityProperties for group properties + keylight direction (PR927) +- Move helper script engines to their own threads (PR853) +- Fix C++20 warnings (PR950) +- Fix access check in getSkeletonModelURLFromScript (PR955) +- SimplifiedUI adjustemnts (PR960) +- Fixed locale problems with cgltf.h (PR978) +- Fixed script signal proxy crashes (PR964) +- Fixed deadlocks in Recording API (PR959) +- Fix tests (PR991) +- Add missing dependencymanager call, fixes test crash (PR994) +- Skip packet capacity test when built in debug mode, as it triggers an assertion (PR993) +- Fix some warnings (PR1003) +- Fix Locker issue in RecordingScriptingInterface (PR1006) + +### Changes +- Update Linux vcpkg to the same as the Windows version (PR751) +- Disable Oculus plugin on Visual Studio 2022 (PR754) +- Reorganize startup to allow more control over plugins (PR716) +- Script performance improvements (PR744) +- Re-enable building Oculus plugin on VS 2022 (PR761) +- Use response files on Ninja for long paths (PR764) +- Improvement in controller scripts performance (PR766) +- Update VCPKG for Linux aarch64 (PR807) +- Linux server gha update (PR812) +- glTF importer using cgltf library (PR835) +- 🔧 Disable building electron screenshare app on windows (PR864) +- Change the hash salt from Vircadia to Overte (PR869) +- Change vircadia launcher dir (PR870) +- Add Oculus to fullbody-enabled headsets list (PR882) +- Add Ubuntu 24.04 to server packaging (PR966) +- Improve network debugging messages to help with Conan PR (PR995) +- Send OpenGL errors to log on debug builds (PR998) + +### Additions +- Add initial benchmarks for the script engine (PR710) +- Add more ram Options (PR763) +- Add VS22 cmake jumpstart script (PR773) +- MToon materials (PR805) +- Add a way to get VCPKG path and hash ID (PR813) +- Entity script logging for script editor (PR673) +- Create app: RenderWithZones Manager (PR806) +- Added WebP support for binary glTF (PR860) +- Support opaque (and black) particles (PR844) +- Create App: Tools tab: CSS&HTML adjustments (PR880) +- Create Application: Advanced Import functionality (PR877) +- Create App.: "Copy Dimensions" and "Paste Dimensions" (PR863) +- Create app: Entity List: "Copy ID" on menu and contextual menu. (PR865) +- Add qByteArray to script value conversion (PR868) +- Custom refresh rate profile (PR899) +- support VRMC_materials_mtoon and KHR_materials_unlit (PR936) +- Add very basic HTTP and HTTPS network tests (PR996) + +### Removals +- Disable Neuron by default (PR753) +- Removing markdown from floof chat (PR769) +- Remove debug print with URL from ModelLoader (PR837) +- Remove legally problematic texture (PR851) + +### Security +- Added simple protection for avatar URL (PR887) +- add canViewAssetURLs domain permissions (PR152) + + +## [2023.11.1] 2023.11.24 ### Fixes - Fixed color conversion for glTF material colors (PR307) @@ -36,14 +171,37 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe - Hugely improved Create app performance in Domains with many entities (PR498) - Fixed an issue that could cause laser pointers to rapidly flash (PR495) - Fixed the connection failure dialog mentioning "Explore" instead of "Places" (PR515) +- Fixed broken documentation and code-completion of the "Script" API namespace (PR450) +- Fixed warning about ForceHtmlAudioOutputDeviceUpdate (PR473) +- Fixed Shield bubble dimensions (PR510) +- Fixed Places app connecting to IP instead of Place name (PR522) +- Fixed Interface scripts failing to shut down (PR521) +- Fixed deadlock related to entity script engines (PR540) +- Fixed leave and join messages in Chat (PR573) +- Fixed crash when closing script log window (PR520) +- Fixed some API documentation (PR598) +- Fixed some missing assets, notably the sound when successfully shaking hands (PR590) +- Fixed multiple script engine reload and shutdown related crashes (PR574) +- Fixed flow bones on avatars with scale ≠ 100 (PR604) +- Fixed curved flow bone chains (PR604) +- Fixed invisible cursor (PR629) +- Fixed loading avatars from URLs containing" =" such as Dropbox (PR634) +- Fixed MicBar type error spam on Windows (PR669) +- Fixed grabbing local entities in VR (PR671) +- Fixed memory leak in entity server and improved its performance (PR690) +- Fixed chat bar appearing in VR (PR672) +- Fixed issues with third-party apps such as ALVR, Virtual Desktop and Streaming Assistant (PR700,PR714) +- Fixed custom graphics settings not being saved (PR706) +- Fixed Script.require behavior (PR697) +- Fixed Entities.setLocalJointRotation not updating (PR708) +- Improved client performance by moving squeezeHands.js to separate thread (PR737) ### Changes -- Replaced Vircadia Metaverse Server with a testing server as federation default (PR330) - An empty audio device list now throws a warning instead of just a debug message (PR347) - Increased the maximum log file size from 512 kiB to 10 MiB (PR342,PR513) - Decreased the amount of retained log files from 100 to 20 (PR342) - Pressing the Return key with the the address/search bar in the Places App selected now navigates you to that address (PR403) -- Replaced QT Script with V8 scripting engine (PR185,PR507,PR519) +- Replaced QT Script with V8 scripting engine (PR185,PR507,PR519,PR566) This is a huge change under the hood, which ended up fixing a lot of issues. Since the new scripting engine does not behave exactly the same as the old one, some scripts might need fixing. The new scripting engine is especially picky when it comes to undefined behaviour. @@ -54,6 +212,14 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe It will also ask once in case of a non-stable build. - Changed the VR overlay to only recenter when moving (PR478) - Added a workaround that prevents most users from needing to press down on the thumbstick to move (PR481,PR512) +- Lowered inertia while moving (PR542) +- Lowered control delays in VR (PR542) + Configurable under Settings → Controls → Calibration +- Changed Home button in Places app to lead to the tutorial by default (PR560) +- Rewritten tutorial wizard in QML (PR645,PR737) +- Disabled Oculus VR plugin by default (PR700,PR714) +- Changed gravity constant to be more realistic (PR729) + This fixes being catapulted into the air when moving up a slope. It also improves taking off, flying, and general movement. ### Additions - Added option to graphics menu for choosing which screen to use for full screen mode (PR302) @@ -62,12 +228,28 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe This allows typing in languages like Japanese or Chinese that make use of an IME. - Added vertical Field Of View setting to graphics menu (PR465) - Added crash reporting to the Domain server, Assignment client, and Oven (PR482) +- Added JavaScript profiling API (PR564) +- Added require() to global scope in scipting API (PR585) +- Added support for HDR lightmaps (PR611) +- Added mouse look (PR607,PR624,PR627,PR662) +- Dropbox URLs to assets now get rewritten to DDL URLs (PR636) +- Added development script to configure avatar smoothing (PR579) +- Added distance based LOD (PR663) + Configurable under Settings → Graphics → Target frame rate +- Added support for QML inside web-entities (PR645) + QML files must be whitelisted in the settings. +- Added Discord rich presence support (PR686,PR723) +- Added command line arguments to ICE server (PR722) ### Removals - Removed outdated Inventory and Marketplace options from Wearables UI (PR303) - Removed outdated Beacon system (PR327) - Removed long deprecated styles-uit and controls-uit QML modules (PR380) - Removed outdated Marketplace and Wallet code (PR381,PR477,PR487) +- Removed Appreciate app from defaults (PR563) +- Removed debug messages from Places app (PR561) +- Removed JQuery dependency from Emote app (PR560) +- Removed File API (PR691) ### Build system - Fixed error in configuration step on some rolling release Linux distributions (PR301) @@ -78,12 +260,21 @@ This project does **not** adhere to [Semantic Versioning](https://semver.org/spe - Updated TBB dependency from version 2019_U8-1 to 2021.5.0 (PR412) - Fixed NVTT compilation on Visual Studio 2022 (PR374) - Disabled libOVR on MSVC 2022 (PR430) -- Added Qt 5.15.9 package for aarch64 Ubuntu 20.04 (PR409) - Fixed build error on aarch64 (PR409) -- Replaced QT Script with V8/libnode (PR185,PR409,PR443) +- Replaced QT Script with V8/libnode (PR185,PR409,PR443,PR535,PR566) - Updated Qt on Windows to 5.15.10 with KDE patches (PR448) - Updated included OpenSSL to 3.0.5 (PR448) +- Updated OpenSSL Windwos dependency (PR448) +- Changed libnode dependency to be built from source (PR452) +- Disabled Crashpad on aarch64 Linux by default (PR526) +- Added discord-rpc dependency (PR686) +- Fixed building with memory debugging (PR704) +- Updated VCPKG on Windows to version 2023.10.19 (PR730) +### Security +- Updated Qt packages to fix CVE-2023-4863 (PR630,PR631) +- Updated Qt packages to fix CVE-2023-5217(PR652,PR653) +- Limited audio recording location (PR691) ## [2022.12.1] 2022.12.24 diff --git a/CMakeLists.txt b/CMakeLists.txt index a46f1963ef..5d566d5da2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,22 +148,22 @@ endif() # OVERTE_WARNINGS # -# Here we add the ability to whitelist warnings we've determined we can't fix, or are safe to +# Here we add the ability to allowlist warnings we've determined we can't fix, or are safe to # ignore for one reason or another. The way of doing so is compiler-specific, so we deal with # the detection of that in cmake, and just pass it down to the code from here. # -# We can also treat warnings as errors. Without the whitelist this will almost certainly lead +# We can also treat warnings as errors. Without the allowlist this will almost certainly lead # to a build failure. -if(NOT DEFINED OVERTE_WARNINGS_WHITELIST) - set(OVERTE_WARNINGS_WHITELIST true CACHE BOOL "Whitelist some warnings we can't currently fix") +if(NOT DEFINED OVERTE_WARNINGS_ALLOWLIST) + set(OVERTE_WARNINGS_ALLOWLIST true CACHE BOOL "Allowlist some warnings we can't currently fix") endif() if(NOT DEFINED OVERTE_WARNINGS_AS_ERRORS) set(OVERTE_WARNINGS_AS_ERRORS false CACHE BOOL "Count warnings as errors") endif() -if(OVERTE_WARNINGS_WHITELIST) +if(OVERTE_WARNINGS_ALLOWLIST) if (NOT WIN32) set(CMAKE_PLATFORM_INFO_DIR "${CMAKE_CURRENT_BINARY_DIR}") include(CMakeDetermineCXXCompiler) @@ -171,15 +171,15 @@ if(OVERTE_WARNINGS_WHITELIST) if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") message("GCC compiler detected, suppressing some unsolvable warnings.") - add_compile_definitions(OVERTE_WARNINGS_WHITELIST_GCC) + add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_GCC) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") message("Clang compiler detected, suppressing some unsolvable warnings.") - add_compile_definitions(OVERTE_WARNINGS_WHITELIST_CLANG) + add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_CLANG) elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "" AND WIN32)) message("Microsoft Visual Studio compiler detected, suppressing some unsolvable warnings.") - add_compile_definitions(OVERTE_WARNINGS_WHITELIST_MSVC) + add_compile_definitions(OVERTE_WARNINGS_ALLOWLIST_MSVC) else() - message("We don't know yet how to whitelist warnings for ${CMAKE_CXX_COMPILER_ID}") + message("We don't know yet how to allowlist warnings for ${CMAKE_CXX_COMPILER_ID}") endif() endif() diff --git a/LICENSE b/LICENSE index 02fef6ca74..dcbbcee40c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Copyright (c) 2013-2019, High Fidelity, Inc. Copyright (c) 2019-2021, Vircadia contributors. -Copyright (c) 2022-2023, Overte e.V. +Copyright (c) 2022-2024, Overte e.V. All rights reserved. https://overte.org diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 788dfeab93..7db768a168 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -277,14 +277,14 @@ void AudioMixer::sendStatsPacket() { #ifdef DEBUG_EVENT_QUEUE QJsonObject qtStats; - _slavePool.queueStats(qtStats); + _workerPool.queueStats(qtStats); statsObject["audio_thread_event_queue"] = qtStats; #endif // general stats statsObject["useDynamicJitterBuffers"] = _numStaticJitterFrames == DISABLE_STATIC_JITTER_FRAMES; - statsObject["threads"] = _slavePool.numThreads(); + statsObject["threads"] = _workerPool.numThreads(); statsObject["trailing_mix_ratio"] = _trailingMixRatio; statsObject["throttling_ratio"] = _throttlingRatio; @@ -433,15 +433,15 @@ void AudioMixer::start() { auto frameTimer = _frameTiming.timer(); - // process (node-isolated) audio packets across slave threads + // process (node-isolated) audio packets across worker threads { auto packetsTimer = _packetsTiming.timer(); - // first clear the concurrent vector of added streams that the slaves will add to when they process packets + // first clear the concurrent vector of added streams that the workers will add to when they process packets _workerSharedData.addedStreams.clear(); nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) { - _slavePool.processPackets(cbegin, cend); + _workerPool.processPackets(cbegin, cend); }); } @@ -463,15 +463,15 @@ void AudioMixer::start() { numToRetain = nodeList->size() * (1.0f - _throttlingRatio); } nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) { - // mix across slave threads + // mix across worker threads auto mixTimer = _mixTiming.timer(); - _slavePool.mix(cbegin, cend, frame, numToRetain); + _workerPool.mix(cbegin, cend, frame, numToRetain); }); // gather stats - _slavePool.each([&](AudioMixerSlave& slave) { - _stats.accumulate(slave.stats); - slave.stats.reset(); + _workerPool.each([&](AudioMixerWorker& worker) { + _stats.accumulate(worker.stats); + worker.stats.reset(); }); ++frame; @@ -573,7 +573,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) { const QString NUM_THREADS = "num_threads"; int numThreads = audioThreadingGroupObject[NUM_THREADS].toString().toInt(&ok); if (ok) { - _slavePool.setNumThreads(numThreads); + _workerPool.setNumThreads(numThreads); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 5b75ed54d2..6365298d87 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -23,7 +23,7 @@ #include #include "AudioMixerStats.h" -#include "AudioMixerSlavePool.h" +#include "AudioMixerWorkerPool.h" class PositionalAudioStream; class AvatarAudioStream; @@ -107,7 +107,7 @@ private: int _numStatFrames { 0 }; AudioMixerStats _stats; - AudioMixerSlavePool _slavePool { _workerSharedData }; + AudioMixerWorkerPool _workerPool { _workerSharedData }; class Timer { public: @@ -153,7 +153,7 @@ private: float _throttleStartTarget = 0.9f; float _throttleBackoffTarget = 0.44f; - AudioMixerSlave::SharedData _workerSharedData; + AudioMixerWorker::SharedData _workerSharedData; }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index a47420a873..625d0f3f08 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -201,9 +201,9 @@ void AudioMixerClientData::parsePerAvatarGainSet(ReceivedMessage& message, const float gain = unpackFloatGainFromByte(packedGain); if (avatarUUID.isNull()) { - // set the MASTER avatar gain - setMasterAvatarGain(gain); - qCDebug(audio) << "Setting MASTER avatar gain for" << uuid << "to" << gain; + // set the PRIMARY avatar gain + setPrimaryAvatarGain(gain); + qCDebug(audio) << "Setting PRIMARY avatar gain for" << uuid << "to" << gain; } else { // set the per-source avatar gain setGainForAvatar(avatarUUID, gain); @@ -218,8 +218,8 @@ void AudioMixerClientData::parseInjectorGainSet(ReceivedMessage& message, const message.readPrimitive(&packedGain); float gain = unpackFloatGainFromByte(packedGain); - setMasterInjectorGain(gain); - qCDebug(audio) << "Setting MASTER injector gain for" << uuid << "to" << gain; + setPrimaryInjectorGain(gain); + qCDebug(audio) << "Setting PRIMARY injector gain for" << uuid << "to" << gain; } bool setGainInStreams(const QUuid &nodeID, float gain, std::vector &streamVector) { diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index b6f26aebc0..6e10585695 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -86,10 +86,10 @@ public: // uses randomization to have the AudioMixer send a stats packet to this node around every second bool shouldSendStats(int frameNumber); - float getMasterAvatarGain() const { return _masterAvatarGain; } - void setMasterAvatarGain(float gain) { _masterAvatarGain = gain; } - float getMasterInjectorGain() const { return _masterInjectorGain; } - void setMasterInjectorGain(float gain) { _masterInjectorGain = gain; } + float getPrimaryAvatarGain() const { return _primaryAvatarGain; } + void setPrimaryAvatarGain(float gain) { _primaryAvatarGain = gain; } + float getPrimaryInjectorGain() const { return _primaryInjectorGain; } + void setPrimaryInjectorGain(float gain) { _primaryInjectorGain = gain; } AudioLimiter audioLimiter; @@ -140,11 +140,11 @@ public: Streams& getStreams() { return _streams; } - // thread-safe, called from AudioMixerSlave(s) while processing ignore packets for other nodes + // thread-safe, called from AudioMixerWorker(s) while processing ignore packets for other nodes void ignoredByNode(QUuid nodeID); void unignoredByNode(QUuid nodeID); - // start of methods called non-concurrently from single AudioMixerSlave mixing for the owning node + // start of methods called non-concurrently from single AudioMixerWorker mixing for the owning node const Node::IgnoredNodeIDs& getNewIgnoredNodeIDs() const { return _newIgnoredNodeIDs; } const Node::IgnoredNodeIDs& getNewUnignoredNodeIDs() const { return _newUnignoredNodeIDs; } @@ -163,7 +163,7 @@ public: bool getHasReceivedFirstMix() const { return _hasReceivedFirstMix; } void setHasReceivedFirstMix(bool hasReceivedFirstMix) { _hasReceivedFirstMix = hasReceivedFirstMix; } - // end of methods called non-concurrently from single AudioMixerSlave + // end of methods called non-concurrently from single AudioMixerWorker signals: void injectorStreamFinished(const QUuid& streamID); @@ -194,8 +194,8 @@ private: int _frameToSendStats { 0 }; - float _masterAvatarGain { 1.0f }; // per-listener mixing gain, applied only to avatars - float _masterInjectorGain { 1.0f }; // per-listener mixing gain, applied only to injectors + float _primaryAvatarGain { 1.0f }; // per-listener mixing gain, applied only to avatars + float _primaryInjectorGain { 1.0f }; // per-listener mixing gain, applied only to injectors CodecPluginPointer _codec; QString _selectedCodecName; diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerWorker.cpp similarity index 93% rename from assignment-client/src/audio/AudioMixerSlave.cpp rename to assignment-client/src/audio/AudioMixerWorker.cpp index 204095ab94..ffe89f1313 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerWorker.cpp @@ -1,5 +1,5 @@ // -// AudioMixerSlave.cpp +// AudioMixerWorker.cpp // assignment-client/src/audio // // Created by Zach Pomerantz on 11/22/16. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AudioMixerSlave.h" +#include "AudioMixerWorker.h" #include @@ -50,12 +50,12 @@ void sendEnvironmentPacket(const SharedNodePointer& node, AudioMixerClientData& // mix helpers inline float approximateGain(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd); -inline float computeGain(float masterAvatarGain, float masterInjectorGain, const AvatarAudioStream& listeningNodeStream, +inline float computeGain(float primaryAvatarGain, float primaryInjectorGain, const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition, float distance); inline float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition); -void AudioMixerSlave::processPackets(const SharedNodePointer& node) { +void AudioMixerWorker::processPackets(const SharedNodePointer& node) { AudioMixerClientData* data = (AudioMixerClientData*)node->getLinkedData(); if (data) { // process packets and collect the number of streams available for this frame @@ -63,14 +63,14 @@ void AudioMixerSlave::processPackets(const SharedNodePointer& node) { } } -void AudioMixerSlave::configureMix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) { +void AudioMixerWorker::configureMix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) { _begin = begin; _end = end; _frame = frame; _numToRetain = numToRetain; } -void AudioMixerSlave::mix(const SharedNodePointer& node) { +void AudioMixerWorker::mix(const SharedNodePointer& node) { // check that the node is valid AudioMixerClientData* data = (AudioMixerClientData*)node->getLinkedData(); if (data == nullptr) { @@ -178,7 +178,7 @@ private: }; -void AudioMixerSlave::addStreams(Node& listener, AudioMixerClientData& listenerData) { +void AudioMixerWorker::addStreams(Node& listener, AudioMixerClientData& listenerData) { auto& ignoredNodeIDs = listener.getIgnoredNodeIDs(); auto& ignoringNodeIDs = listenerData.getIgnoringNodeIDs(); @@ -229,7 +229,7 @@ void AudioMixerSlave::addStreams(Node& listener, AudioMixerClientData& listenerD } } -bool shouldBeRemoved(const MixableStream& stream, const AudioMixerSlave::SharedData& sharedData) { +bool shouldBeRemoved(const MixableStream& stream, const AudioMixerWorker::SharedData& sharedData) { return (contains(sharedData.removedNodes, stream.nodeStreamID.nodeLocalID) || contains(sharedData.removedStreams, stream.nodeStreamID)); }; @@ -306,7 +306,7 @@ float approximateVolume(const MixableStream& stream, const AvatarAudioStream* li return stream.positionalStream->getLastPopOutputTrailingLoudness() * gain; }; -bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { +bool AudioMixerWorker::prepareMix(const SharedNodePointer& listener) { AvatarAudioStream* listenerAudioStream = static_cast(listener->getLinkedData())->getAvatarAudioStream(); AudioMixerClientData* listenerData = static_cast(listener->getLinkedData()); @@ -338,8 +338,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { } if (!isThrottling) { - updateHRTFParameters(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), - listenerData->getMasterInjectorGain()); + updateHRTFParameters(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), + listenerData->getPrimaryInjectorGain()); } return false; }); @@ -363,8 +363,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { } if (!isThrottling) { - updateHRTFParameters(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), - listenerData->getMasterInjectorGain()); + updateHRTFParameters(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), + listenerData->getPrimaryInjectorGain()); } return false; }); @@ -387,7 +387,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { return true; } - addStream(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), listenerData->getMasterInjectorGain(), + addStream(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), listenerData->getPrimaryInjectorGain(), isSoloing); if (shouldBeInactive(stream)) { @@ -423,7 +423,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { return true; } - addStream(stream, *listenerAudioStream, listenerData->getMasterAvatarGain(), listenerData->getMasterInjectorGain(), + addStream(stream, *listenerAudioStream, listenerData->getPrimaryAvatarGain(), listenerData->getPrimaryInjectorGain(), isSoloing); if (shouldBeInactive(stream)) { @@ -489,10 +489,10 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { return hasAudio; } -void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStream, +void AudioMixerWorker::addStream(AudioMixerClientData::MixableStream& mixableStream, AvatarAudioStream& listeningNodeStream, - float masterAvatarGain, - float masterInjectorGain, + float primaryAvatarGain, + float primaryInjectorGain, bool isSoloing) { ++stats.totalMixes; @@ -505,8 +505,8 @@ void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStre float distance = glm::max(glm::length(relativePosition), EPSILON); float gain = isEcho ? 1.0f - : (isSoloing ? masterAvatarGain - : computeGain(masterAvatarGain, masterInjectorGain, listeningNodeStream, *streamToAdd, + : (isSoloing ? primaryAvatarGain + : computeGain(primaryAvatarGain, primaryInjectorGain, listeningNodeStream, *streamToAdd, relativePosition, distance)); float azimuth = isEcho ? 0.0f : computeAzimuth(listeningNodeStream, listeningNodeStream, relativePosition); @@ -575,10 +575,10 @@ void AudioMixerSlave::addStream(AudioMixerClientData::MixableStream& mixableStre } } -void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream, +void AudioMixerWorker::updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream, AvatarAudioStream& listeningNodeStream, - float masterAvatarGain, - float masterInjectorGain) { + float primaryAvatarGain, + float primaryInjectorGain) { auto streamToAdd = mixableStream.positionalStream; // check if this is a server echo of a source back to itself @@ -587,7 +587,7 @@ void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream& glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream.getPosition(); float distance = glm::max(glm::length(relativePosition), EPSILON); - float gain = isEcho ? 1.0f : computeGain(masterAvatarGain, masterInjectorGain, listeningNodeStream, *streamToAdd, + float gain = isEcho ? 1.0f : computeGain(primaryAvatarGain, primaryInjectorGain, listeningNodeStream, *streamToAdd, relativePosition, distance); float azimuth = isEcho ? 0.0f : computeAzimuth(listeningNodeStream, listeningNodeStream, relativePosition); @@ -596,7 +596,7 @@ void AudioMixerSlave::updateHRTFParameters(AudioMixerClientData::MixableStream& ++stats.hrtfUpdates; } -void AudioMixerSlave::resetHRTFState(AudioMixerClientData::MixableStream& mixableStream) { +void AudioMixerWorker::resetHRTFState(AudioMixerClientData::MixableStream& mixableStream) { mixableStream.hrtf->reset(); ++stats.hrtfResets; } @@ -713,7 +713,7 @@ float approximateGain(const AvatarAudioStream& listeningNodeStream, const Positi // injector: apply attenuation if (streamToAdd.getType() == PositionalAudioStream::Injector) { gain *= reinterpret_cast(&streamToAdd)->getAttenuationRatio(); - // injector: skip master gain + // injector: skip primary gain } // avatar: skip attenuation - it is too costly to approximate @@ -723,11 +723,11 @@ float approximateGain(const AvatarAudioStream& listeningNodeStream, const Positi float distance = glm::length(relativePosition); return gain / distance; - // avatar: skip master gain + // avatar: skip primary gain } -float computeGain(float masterAvatarGain, - float masterInjectorGain, +float computeGain(float primaryAvatarGain, + float primaryInjectorGain, const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition, @@ -737,8 +737,8 @@ float computeGain(float masterAvatarGain, // injector: apply attenuation if (streamToAdd.getType() == PositionalAudioStream::Injector) { gain *= reinterpret_cast(&streamToAdd)->getAttenuationRatio(); - // apply master gain - gain *= masterInjectorGain; + // apply primary gain + gain *= primaryInjectorGain; // avatar: apply fixed off-axis attenuation to make them quieter as they turn away } else if (streamToAdd.getType() == PositionalAudioStream::Microphone) { @@ -754,8 +754,8 @@ float computeGain(float masterAvatarGain, gain *= offAxisCoefficient; - // apply master gain - gain *= masterAvatarGain; + // apply primary gain + gain *= primaryAvatarGain; } auto& audioZones = AudioMixer::getAudioZones(); diff --git a/assignment-client/src/audio/AudioMixerSlave.h b/assignment-client/src/audio/AudioMixerWorker.h similarity index 84% rename from assignment-client/src/audio/AudioMixerSlave.h rename to assignment-client/src/audio/AudioMixerWorker.h index 03668c8146..cff4094f0c 100644 --- a/assignment-client/src/audio/AudioMixerSlave.h +++ b/assignment-client/src/audio/AudioMixerWorker.h @@ -1,5 +1,5 @@ // -// AudioMixerSlave.h +// AudioMixerWorker.h // assignment-client/src/audio // // Created by Zach Pomerantz on 11/22/16. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AudioMixerSlave_h -#define hifi_AudioMixerSlave_h +#ifndef hifi_AudioMixerWorker_h +#define hifi_AudioMixerWorker_h #if !defined(Q_MOC_RUN) // Work around https://bugreports.qt.io/browse/QTBUG-80990 @@ -31,7 +31,7 @@ class AvatarAudioStream; class AudioHRTF; -class AudioMixerSlave { +class AudioMixerWorker { public: using ConstIter = NodeList::const_iterator; @@ -41,7 +41,7 @@ public: std::vector removedStreams; }; - AudioMixerSlave(SharedData& sharedData) : _sharedData(sharedData) {}; + AudioMixerWorker(SharedData& sharedData) : _sharedData(sharedData) {}; // process packets for a given node (requires no configuration) void processPackets(const SharedNodePointer& node); @@ -60,13 +60,13 @@ private: bool prepareMix(const SharedNodePointer& listener); void addStream(AudioMixerClientData::MixableStream& mixableStream, AvatarAudioStream& listeningNodeStream, - float masterAvatarGain, - float masterInjectorGain, + float primaryAvatarGain, + float primaryInjectorGain, bool isSoloing); void updateHRTFParameters(AudioMixerClientData::MixableStream& mixableStream, AvatarAudioStream& listeningNodeStream, - float masterAvatarGain, - float masterInjectorGain); + float primaryAvatarGain, + float primaryInjectorGain); void resetHRTFState(AudioMixerClientData::MixableStream& mixableStream); void addStreams(Node& listener, AudioMixerClientData& listenerData); @@ -84,4 +84,4 @@ private: SharedData& _sharedData; }; -#endif // hifi_AudioMixerSlave_h +#endif // hifi_AudioMixerWorker_h diff --git a/assignment-client/src/audio/AudioMixerSlavePool.cpp b/assignment-client/src/audio/AudioMixerWorkerPool.cpp similarity index 62% rename from assignment-client/src/audio/AudioMixerSlavePool.cpp rename to assignment-client/src/audio/AudioMixerWorkerPool.cpp index e8a2909acb..84b46949b0 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.cpp +++ b/assignment-client/src/audio/AudioMixerWorkerPool.cpp @@ -1,5 +1,5 @@ // -// AudioMixerSlavePool.cpp +// AudioMixerWorkerPool.cpp // assignment-client/src/audio // // Created by Zach Pomerantz on 11/16/2016. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AudioMixerSlavePool.h" +#include "AudioMixerWorkerPool.h" #include @@ -18,7 +18,7 @@ #include -void AudioMixerSlaveThread::run() { +void AudioMixerWorkerThread::run() { while (true) { wait(); @@ -36,10 +36,10 @@ void AudioMixerSlaveThread::run() { } } -void AudioMixerSlaveThread::wait() { +void AudioMixerWorkerThread::wait() { { Lock lock(_pool._mutex); - _pool._slaveCondition.wait(lock, [&] { + _pool._workerCondition.wait(lock, [&] { assert(_pool._numStarted <= _pool._numThreads); return _pool._numStarted != _pool._numThreads; }); @@ -52,7 +52,7 @@ void AudioMixerSlaveThread::wait() { _function = _pool._function; } -void AudioMixerSlaveThread::notify(bool stopping) { +void AudioMixerWorkerThread::notify(bool stopping) { { Lock lock(_pool._mutex); assert(_pool._numFinished < _pool._numThreads); @@ -64,26 +64,26 @@ void AudioMixerSlaveThread::notify(bool stopping) { _pool._poolCondition.notify_one(); } -bool AudioMixerSlaveThread::try_pop(SharedNodePointer& node) { +bool AudioMixerWorkerThread::try_pop(SharedNodePointer& node) { return _pool._queue.try_pop(node); } -void AudioMixerSlavePool::processPackets(ConstIter begin, ConstIter end) { - _function = &AudioMixerSlave::processPackets; - _configure = [](AudioMixerSlave& slave) {}; +void AudioMixerWorkerPool::processPackets(ConstIter begin, ConstIter end) { + _function = &AudioMixerWorker::processPackets; + _configure = [](AudioMixerWorker& worker) {}; run(begin, end); } -void AudioMixerSlavePool::mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) { - _function = &AudioMixerSlave::mix; - _configure = [=](AudioMixerSlave& slave) { - slave.configureMix(_begin, _end, frame, numToRetain); +void AudioMixerWorkerPool::mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain) { + _function = &AudioMixerWorker::mix; + _configure = [=](AudioMixerWorker& worker) { + worker.configureMix(_begin, _end, frame, numToRetain); }; run(begin, end); } -void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) { +void AudioMixerWorkerPool::run(ConstIter begin, ConstIter end) { _begin = begin; _end = end; @@ -97,7 +97,7 @@ void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) { // run _numStarted = _numFinished = 0; - _slaveCondition.notify_all(); + _workerCondition.notify_all(); // wait _poolCondition.wait(lock, [&] { @@ -111,17 +111,17 @@ void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) { assert(_queue.empty()); } -void AudioMixerSlavePool::each(std::function functor) { - for (auto& slave : _slaves) { - functor(*slave.get()); +void AudioMixerWorkerPool::each(std::function functor) { + for (auto& worker : _workers) { + functor(*worker.get()); } } #ifdef DEBUG_EVENT_QUEUE -void AudioMixerSlavePool::queueStats(QJsonObject& stats) { +void AudioMixerWorkerPool::queueStats(QJsonObject& stats) { unsigned i = 0; - for (auto& slave : _slaves) { - int queueSize = ::hifi::qt::getEventQueueSize(slave.get()); + for (auto& worker : _workers) { + int queueSize = ::hifi::qt::getEventQueueSize(worker.get()); QString queueName = QString("audio_thread_event_queue_%1").arg(i); stats[queueName] = queueSize; @@ -130,7 +130,7 @@ void AudioMixerSlavePool::queueStats(QJsonObject& stats) { } #endif // DEBUG_EVENT_QUEUE -void AudioMixerSlavePool::setNumThreads(int numThreads) { +void AudioMixerWorkerPool::setNumThreads(int numThreads) { // clamp to allowed size { int maxThreads = QThread::idealThreadCount(); @@ -150,36 +150,36 @@ void AudioMixerSlavePool::setNumThreads(int numThreads) { resize(numThreads); } -void AudioMixerSlavePool::resize(int numThreads) { - assert(_numThreads == (int)_slaves.size()); +void AudioMixerWorkerPool::resize(int numThreads) { + assert(_numThreads == (int)_workers.size()); qDebug("%s: set %d threads (was %d)", __FUNCTION__, numThreads, _numThreads); Lock lock(_mutex); if (numThreads > _numThreads) { - // start new slaves + // start new workers for (int i = 0; i < numThreads - _numThreads; ++i) { - auto slave = new AudioMixerSlaveThread(*this, _workerSharedData); - QObject::connect(slave, &QThread::started, [] { setThreadName("AudioMixerSlaveThread"); }); - slave->start(); - _slaves.emplace_back(slave); + auto worker = new AudioMixerWorkerThread(*this, _workerSharedData); + QObject::connect(worker, &QThread::started, [] { setThreadName("AudioMixerWorkerThread"); }); + worker->start(); + _workers.emplace_back(worker); } } else if (numThreads < _numThreads) { - auto extraBegin = _slaves.begin() + numThreads; + auto extraBegin = _workers.begin() + numThreads; - // mark slaves to stop... - auto slave = extraBegin; - while (slave != _slaves.end()) { - (*slave)->_stop = true; - ++slave; + // mark workers to stop... + auto worker = extraBegin; + while (worker != _workers.end()) { + (*worker)->_stop = true; + ++worker; } // ...cycle them until they do stop... _numStopped = 0; while (_numStopped != (_numThreads - numThreads)) { _numStarted = _numFinished = _numStopped; - _slaveCondition.notify_all(); + _workerCondition.notify_all(); _poolCondition.wait(lock, [&] { assert(_numFinished <= _numThreads); return _numFinished == _numThreads; @@ -187,18 +187,18 @@ void AudioMixerSlavePool::resize(int numThreads) { } // ...wait for threads to finish... - slave = extraBegin; - while (slave != _slaves.end()) { - QThread* thread = reinterpret_cast(slave->get()); + worker = extraBegin; + while (worker != _workers.end()) { + QThread* thread = reinterpret_cast(worker->get()); static const int MAX_THREAD_WAIT_TIME = 10; thread->wait(MAX_THREAD_WAIT_TIME); - ++slave; + ++worker; } // ...and erase them - _slaves.erase(extraBegin, _slaves.end()); + _workers.erase(extraBegin, _workers.end()); } _numThreads = _numStarted = _numFinished = numThreads; - assert(_numThreads == (int)_slaves.size()); + assert(_numThreads == (int)_workers.size()); } diff --git a/assignment-client/src/audio/AudioMixerSlavePool.h b/assignment-client/src/audio/AudioMixerWorkerPool.h similarity index 54% rename from assignment-client/src/audio/AudioMixerSlavePool.h rename to assignment-client/src/audio/AudioMixerWorkerPool.h index 3807db0541..18817f0d2e 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.h +++ b/assignment-client/src/audio/AudioMixerWorkerPool.h @@ -1,5 +1,5 @@ // -// AudioMixerSlavePool.h +// AudioMixerWorkerPool.h // assignment-client/src/audio // // Created by Zach Pomerantz on 11/16/2016. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AudioMixerSlavePool_h -#define hifi_AudioMixerSlavePool_h +#ifndef hifi_AudioMixerWorkerPool_h +#define hifi_AudioMixerWorkerPool_h #include #include @@ -20,37 +20,37 @@ #include #include -#include "AudioMixerSlave.h" +#include "AudioMixerWorker.h" -class AudioMixerSlavePool; +class AudioMixerWorkerPool; -class AudioMixerSlaveThread : public QThread, public AudioMixerSlave { +class AudioMixerWorkerThread : public QThread, public AudioMixerWorker { Q_OBJECT using ConstIter = NodeList::const_iterator; using Mutex = std::mutex; using Lock = std::unique_lock; public: - AudioMixerSlaveThread(AudioMixerSlavePool& pool, AudioMixerSlave::SharedData& sharedData) - : AudioMixerSlave(sharedData), _pool(pool) {} + AudioMixerWorkerThread(AudioMixerWorkerPool& pool, AudioMixerWorker::SharedData& sharedData) + : AudioMixerWorker(sharedData), _pool(pool) {} void run() override final; private: - friend class AudioMixerSlavePool; + friend class AudioMixerWorkerPool; void wait(); void notify(bool stopping); bool try_pop(SharedNodePointer& node); - AudioMixerSlavePool& _pool; - void (AudioMixerSlave::*_function)(const SharedNodePointer& node) { nullptr }; + AudioMixerWorkerPool& _pool; + void (AudioMixerWorker::*_function)(const SharedNodePointer& node) { nullptr }; bool _stop { false }; }; -// Slave pool for audio mixers -// AudioMixerSlavePool is not thread-safe! It should be instantiated and used from a single thread. -class AudioMixerSlavePool { +// Worker pool for audio mixers +// AudioMixerWorkerPool is not thread-safe! It should be instantiated and used from a single thread. +class AudioMixerWorkerPool { using Queue = tbb::concurrent_queue; using Mutex = std::mutex; using Lock = std::unique_lock; @@ -59,18 +59,18 @@ class AudioMixerSlavePool { public: using ConstIter = NodeList::const_iterator; - AudioMixerSlavePool(AudioMixerSlave::SharedData& sharedData, int numThreads = QThread::idealThreadCount()) + AudioMixerWorkerPool(AudioMixerWorker::SharedData& sharedData, int numThreads = QThread::idealThreadCount()) : _workerSharedData(sharedData) { setNumThreads(numThreads); } - ~AudioMixerSlavePool() { resize(0); } + ~AudioMixerWorkerPool() { resize(0); } - // process packets on slave threads + // process packets on worker threads void processPackets(ConstIter begin, ConstIter end); - // mix on slave threads + // mix on worker threads void mix(ConstIter begin, ConstIter end, unsigned int frame, int numToRetain); - // iterate over all slaves - void each(std::function functor); + // iterate over all workers + void each(std::function functor); #ifdef DEBUG_EVENT_QUEUE void queueStats(QJsonObject& stats); @@ -83,18 +83,18 @@ private: void run(ConstIter begin, ConstIter end); void resize(int numThreads); - std::vector> _slaves; + std::vector> _workers; - friend void AudioMixerSlaveThread::wait(); - friend void AudioMixerSlaveThread::notify(bool stopping); - friend bool AudioMixerSlaveThread::try_pop(SharedNodePointer& node); + friend void AudioMixerWorkerThread::wait(); + friend void AudioMixerWorkerThread::notify(bool stopping); + friend bool AudioMixerWorkerThread::try_pop(SharedNodePointer& node); // synchronization state Mutex _mutex; - ConditionVariable _slaveCondition; + ConditionVariable _workerCondition; ConditionVariable _poolCondition; - void (AudioMixerSlave::*_function)(const SharedNodePointer& node); - std::function _configure; + void (AudioMixerWorker::*_function)(const SharedNodePointer& node); + std::function _configure; int _numThreads { 0 }; int _numStarted { 0 }; // guarded by _mutex int _numFinished { 0 }; // guarded by _mutex @@ -105,7 +105,7 @@ private: ConstIter _begin; ConstIter _end; - AudioMixerSlave::SharedData& _workerSharedData; + AudioMixerWorker::SharedData& _workerSharedData; }; -#endif // hifi_AudioMixerSlavePool_h +#endif // hifi_AudioMixerWorkerPool_h diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 7279627daf..80c3e1ae95 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -60,7 +60,7 @@ bool AvatarMixer::SessionDisplayName::operator<(const SessionDisplayName& rhs) c AvatarMixer::AvatarMixer(ReceivedMessage& message) : ThreadedAssignment(message), - _slavePool(&_slaveSharedData) + _workerPool(&_workerSharedData) { DependencyManager::registerInheritance(); DependencyManager::set(); @@ -297,7 +297,7 @@ void AvatarMixer::start() { auto end = usecTimestampNow(); _processQueuedAvatarDataPacketsLockWaitElapsedTime += (end - start); - _slavePool.processIncomingPackets(cbegin, cend); + _workerPool.processIncomingPackets(cbegin, cend); }, &lockWait, &nodeTransform, &functor); auto end = usecTimestampNow(); _processQueuedAvatarDataPacketsElapsedTime += (end - start); @@ -333,7 +333,7 @@ void AvatarMixer::start() { auto start = usecTimestampNow(); nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) { auto start = usecTimestampNow(); - _slavePool.broadcastAvatarData(cbegin, cend, _lastFrameTimestamp, _maxKbpsPerNode, _throttlingRatio); + _workerPool.broadcastAvatarData(cbegin, cend, _lastFrameTimestamp, _maxKbpsPerNode, _throttlingRatio); auto end = usecTimestampNow(); _broadcastAvatarDataInner += (end - start); }, &lockWait, &nodeTransform, &functor); @@ -761,14 +761,14 @@ void AvatarMixer::sendStatsPacket() { QJsonObject statsObject; statsObject["broadcast_loop_rate"] = _loopRate.rate(); - statsObject["threads"] = _slavePool.numThreads(); + statsObject["threads"] = _workerPool.numThreads(); statsObject["trailing_mix_ratio"] = _trailingMixRatio; statsObject["throttling_ratio"] = _throttlingRatio; #ifdef DEBUG_EVENT_QUEUE QJsonObject qtStats; - _slavePool.queueStats(qtStats); + _workerPool.queueStats(qtStats); statsObject["avatar_thread_event_queue"] = qtStats; #endif @@ -821,41 +821,41 @@ void AvatarMixer::sendStatsPacket() { statsObject["parallelTasks"] = parallelTasks; - AvatarMixerSlaveStats aggregateStats; + AvatarMixerWorkerStats aggregateStats; // gather stats - _slavePool.each([&](AvatarMixerSlave& slave) { - AvatarMixerSlaveStats stats; - slave.harvestStats(stats); + _workerPool.each([&](AvatarMixerWorker& worker) { + AvatarMixerWorkerStats stats; + worker.harvestStats(stats); aggregateStats += stats; }); - QJsonObject slavesAggregatObject; + QJsonObject workersAggregatObject; - slavesAggregatObject["received_1_nodesProcessed"] = TIGHT_LOOP_STAT(aggregateStats.nodesProcessed); + workersAggregatObject["received_1_nodesProcessed"] = TIGHT_LOOP_STAT(aggregateStats.nodesProcessed); - slavesAggregatObject["sent_1_nodesBroadcastedTo"] = TIGHT_LOOP_STAT(aggregateStats.nodesBroadcastedTo); + workersAggregatObject["sent_1_nodesBroadcastedTo"] = TIGHT_LOOP_STAT(aggregateStats.nodesBroadcastedTo); float averageNodes = ((float)aggregateStats.nodesBroadcastedTo / (float)tightLoopFrames); float averageOthersIncluded = averageNodes ? aggregateStats.numOthersIncluded / averageNodes : 0.0f; - slavesAggregatObject["sent_2_averageOthersIncluded"] = TIGHT_LOOP_STAT(averageOthersIncluded); + workersAggregatObject["sent_2_averageOthersIncluded"] = TIGHT_LOOP_STAT(averageOthersIncluded); float averageOverBudgetAvatars = averageNodes ? aggregateStats.overBudgetAvatars / averageNodes : 0.0f; - slavesAggregatObject["sent_3_averageOverBudgetAvatars"] = TIGHT_LOOP_STAT(averageOverBudgetAvatars); - slavesAggregatObject["sent_4_averageDataBytes"] = TIGHT_LOOP_STAT(aggregateStats.numDataBytesSent); - slavesAggregatObject["sent_5_averageTraitsBytes"] = TIGHT_LOOP_STAT(aggregateStats.numTraitsBytesSent); - slavesAggregatObject["sent_6_averageIdentityBytes"] = TIGHT_LOOP_STAT(aggregateStats.numIdentityBytesSent); - slavesAggregatObject["sent_7_averageHeroAvatars"] = TIGHT_LOOP_STAT(aggregateStats.numHeroesIncluded); + workersAggregatObject["sent_3_averageOverBudgetAvatars"] = TIGHT_LOOP_STAT(averageOverBudgetAvatars); + workersAggregatObject["sent_4_averageDataBytes"] = TIGHT_LOOP_STAT(aggregateStats.numDataBytesSent); + workersAggregatObject["sent_5_averageTraitsBytes"] = TIGHT_LOOP_STAT(aggregateStats.numTraitsBytesSent); + workersAggregatObject["sent_6_averageIdentityBytes"] = TIGHT_LOOP_STAT(aggregateStats.numIdentityBytesSent); + workersAggregatObject["sent_7_averageHeroAvatars"] = TIGHT_LOOP_STAT(aggregateStats.numHeroesIncluded); - slavesAggregatObject["timing_1_processIncomingPackets"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.processIncomingPacketsElapsedTime); - slavesAggregatObject["timing_2_ignoreCalculation"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.ignoreCalculationElapsedTime); - slavesAggregatObject["timing_3_toByteArray"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.toByteArrayElapsedTime); - slavesAggregatObject["timing_4_avatarDataPacking"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.avatarDataPackingElapsedTime); - slavesAggregatObject["timing_5_packetSending"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.packetSendingElapsedTime); - slavesAggregatObject["timing_6_jobElapsedTime"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.jobElapsedTime); + workersAggregatObject["timing_1_processIncomingPackets"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.processIncomingPacketsElapsedTime); + workersAggregatObject["timing_2_ignoreCalculation"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.ignoreCalculationElapsedTime); + workersAggregatObject["timing_3_toByteArray"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.toByteArrayElapsedTime); + workersAggregatObject["timing_4_avatarDataPacking"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.avatarDataPackingElapsedTime); + workersAggregatObject["timing_5_packetSending"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.packetSendingElapsedTime); + workersAggregatObject["timing_6_jobElapsedTime"] = TIGHT_LOOP_STAT_UINT64(aggregateStats.jobElapsedTime); - statsObject["slaves_aggregate (per frame)"] = slavesAggregatObject; + statsObject["workers_aggregate (per frame)"] = workersAggregatObject; _handleViewFrustumPacketElapsedTime = 0; _handleAvatarIdentityPacketElapsedTime = 0; @@ -1016,9 +1016,9 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { numThreads = 1; } qCDebug(avatars) << "Avatar mixer will use specified number of threads:" << numThreads; - _slavePool.setNumThreads(numThreads); + _workerPool.setNumThreads(numThreads); } else { - qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _slavePool.numThreads() << "threads."; + qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _workerPool.numThreads() << "threads."; } { @@ -1035,7 +1035,7 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { static const QString PRIORITY_FRACTION_KEY = "priority_fraction"; if (avatarMixerGroupObject.contains(PRIORITY_FRACTION_KEY)) { float priorityFraction = float(avatarMixerGroupObject[PRIORITY_FRACTION_KEY].toDouble()); - _slavePool.setPriorityReservedFraction(std::min(std::max(0.0f, priorityFraction), 1.0f)); + _workerPool.setPriorityReservedFraction(std::min(std::max(0.0f, priorityFraction), 1.0f)); qCDebug(avatars) << "Avatar mixer reserving" << priorityFraction << "of bandwidth for priority avatars"; } } @@ -1058,23 +1058,23 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { qCDebug(avatars) << "This domain requires a minimum avatar height of" << _domainMinimumHeight << "and a maximum avatar height of" << _domainMaximumHeight; - static const QString AVATAR_WHITELIST_OPTION = "avatar_whitelist"; - _slaveSharedData.skeletonURLWhitelist = avatarMixerGroupObject[AVATAR_WHITELIST_OPTION] + static const QString AVATAR_ALLOWLIST_OPTION = "avatar_allowlist"; + _workerSharedData.skeletonURLAllowlist = avatarMixerGroupObject[AVATAR_ALLOWLIST_OPTION] .toString().split(',', Qt::KeepEmptyParts); static const QString REPLACEMENT_AVATAR_OPTION = "replacement_avatar"; - _slaveSharedData.skeletonReplacementURL = avatarMixerGroupObject[REPLACEMENT_AVATAR_OPTION] + _workerSharedData.skeletonReplacementURL = avatarMixerGroupObject[REPLACEMENT_AVATAR_OPTION] .toString(); - if (_slaveSharedData.skeletonURLWhitelist.count() == 1 && _slaveSharedData.skeletonURLWhitelist[0].isEmpty()) { + if (_workerSharedData.skeletonURLAllowlist.count() == 1 && _workerSharedData.skeletonURLAllowlist[0].isEmpty()) { // KeepEmptyParts above will parse "," as ["", ""] (which is ok), but "" as [""] (which is not ok). - _slaveSharedData.skeletonURLWhitelist.clear(); + _workerSharedData.skeletonURLAllowlist.clear(); } - if (_slaveSharedData.skeletonURLWhitelist.isEmpty()) { + if (_workerSharedData.skeletonURLAllowlist.isEmpty()) { qCDebug(avatars) << "All avatars are allowed."; } else { - qCDebug(avatars) << "Avatars other than" << _slaveSharedData.skeletonURLWhitelist << "will be replaced by" << (_slaveSharedData.skeletonReplacementURL.isEmpty() ? "default" : _slaveSharedData.skeletonReplacementURL.toString()); + qCDebug(avatars) << "Avatars other than" << _workerSharedData.skeletonURLAllowlist << "will be replaced by" << (_workerSharedData.skeletonReplacementURL.isEmpty() ? "default" : _workerSharedData.skeletonReplacementURL.toString()); } } @@ -1099,7 +1099,7 @@ void AvatarMixer::setupEntityQuery() { priorityZoneQuery["name"] = true; // Handy for debugging. _entityViewer.getOctreeQuery().setJSONParameters(priorityZoneQuery); - _slaveSharedData.entityTree = entityTree; + _workerSharedData.entityTree = entityTree; } void AvatarMixer::handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode) { diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 92821277de..9af377231e 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -26,7 +26,7 @@ #include "../entities/EntityTreeHeadlessViewer.h" #include "AvatarMixerClientData.h" -#include "AvatarMixerSlavePool.h" +#include "AvatarMixerWorkerPool.h" /// Handles assignments of type AvatarMixer - distribution of avatar data to various clients class AvatarMixer : public ThreadedAssignment { @@ -153,8 +153,8 @@ private: RateCounter<> _loopRate; // this is the rate that the main thread tight loop runs - AvatarMixerSlavePool _slavePool; - SlaveSharedData _slaveSharedData; + AvatarMixerWorkerPool _workerPool; + WorkerSharedData _workerSharedData; }; #endif // hifi_AvatarMixer_h diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 67085b4adf..1e9046a2af 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -21,7 +21,7 @@ #include "AvatarLogging.h" -#include "AvatarMixerSlave.h" +#include "AvatarMixerWorker.h" AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID nodeLocalID) : NodeData(nodeID, nodeLocalID) { // in case somebody calls getSessionUUID on the AvatarData instance, make sure it has the right ID @@ -52,7 +52,7 @@ void AvatarMixerClientData::queuePacket(QSharedPointer message, _packetQueue.push(message); } -int AvatarMixerClientData::processPackets(const SlaveSharedData& slaveSharedData) { +int AvatarMixerClientData::processPackets(const WorkerSharedData& workerSharedData) { int packetsProcessed = 0; SharedNodePointer node = _packetQueue.node; assert(_packetQueue.empty() || node); @@ -65,10 +65,10 @@ int AvatarMixerClientData::processPackets(const SlaveSharedData& slaveSharedData switch (packet->getType()) { case PacketType::AvatarData: - parseData(*packet, slaveSharedData); + parseData(*packet, workerSharedData); break; case PacketType::SetAvatarTraits: - processSetTraitsMessage(*packet, slaveSharedData, *node); + processSetTraitsMessage(*packet, workerSharedData, *node); break; case PacketType::BulkAvatarTraitsAck: processBulkAvatarTraitsAckMessage(*packet); @@ -127,7 +127,7 @@ struct FindContainingZone { } // namespace -int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveSharedData& slaveSharedData) { +int AvatarMixerClientData::parseData(ReceivedMessage& message, const WorkerSharedData& workerSharedData) { // pull the sequence number from the data first uint16_t sequenceNumber; @@ -150,7 +150,7 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveShared auto newPosition = _avatar->getClientGlobalPosition(); if (newPosition != oldPosition || _avatar->getNeedsHeroCheck()) { - EntityTree& entityTree = *slaveSharedData.entityTree; + EntityTree& entityTree = *workerSharedData.entityTree; FindContainingZone findContainingZone{ newPosition }; entityTree.recurseTreeWithOperation(&FindContainingZone::operation, &findContainingZone); bool currentlyHasPriority = findContainingZone.isInPriorityZone; @@ -176,7 +176,7 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message, const SlaveShared } void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, - const SlaveSharedData& slaveSharedData, + const WorkerSharedData& workerSharedData, Node& sendingNode) { // Trying to read more bytes than available, bail if (message.getBytesLeftToRead() < qint64(sizeof(AvatarTraits::TraitVersion))) { @@ -221,8 +221,8 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, _avatar->processTrait(traitType, message.read(traitSize)); _lastReceivedTraitVersions[traitType] = packetTraitVersion; if (traitType == AvatarTraits::SkeletonModelURL) { - // special handling for skeleton model URL, since we need to make sure it is in the whitelist - checkSkeletonURLAgainstWhitelist(slaveSharedData, sendingNode, packetTraitVersion); + // special handling for skeleton model URL, since we need to make sure it is in the allowlist + checkSkeletonURLAgainstAllowlist(workerSharedData, sendingNode, packetTraitVersion); } anyTraitsChanged = true; @@ -366,36 +366,36 @@ void AvatarMixerClientData::processBulkAvatarTraitsAckMessage(ReceivedMessage& m } } -void AvatarMixerClientData::checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, +void AvatarMixerClientData::checkSkeletonURLAgainstAllowlist(const WorkerSharedData& workerSharedData, Node& sendingNode, AvatarTraits::TraitVersion traitVersion) { - const auto& whitelist = slaveSharedData.skeletonURLWhitelist; + const auto& allowlist = workerSharedData.skeletonURLAllowlist; - if (!whitelist.isEmpty()) { - bool inWhitelist = false; + if (!allowlist.isEmpty()) { + bool inAllowlist = false; auto avatarURL = _avatar->getSkeletonModelURL(); - // The avatar is in the whitelist if: - // 1. The avatar's URL's host matches one of the hosts of the URLs in the whitelist AND - // 2. The avatar's URL's path starts with the path of that same URL in the whitelist - for (const auto& whiteListedPrefix : whitelist) { - auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix); - // check if this script URL matches the whitelist domain and, optionally, is beneath the path - if (avatarURL.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 && - avatarURL.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) { - inWhitelist = true; + // The avatar is in the allowlist if: + // 1. The avatar's URL's host matches one of the hosts of the URLs in the allowlist AND + // 2. The avatar's URL's path starts with the path of that same URL in the allowlist + for (const auto& allowListedPrefix : allowlist) { + auto allowListURL = QUrl::fromUserInput(allowListedPrefix); + // check if this script URL matches the allowlist domain and, optionally, is beneath the path + if (avatarURL.host().compare(allowListURL.host(), Qt::CaseInsensitive) == 0 && + avatarURL.path().startsWith(allowListURL.path(), Qt::CaseInsensitive)) { + inAllowlist = true; break; } } - if (!inWhitelist) { + if (!inAllowlist) { // make sure we're not unecessarily overriding the default avatar with the default avatar - if (_avatar->getWireSafeSkeletonModelURL() != slaveSharedData.skeletonReplacementURL) { + if (_avatar->getWireSafeSkeletonModelURL() != workerSharedData.skeletonReplacementURL) { // we need to change this avatar's skeleton URL, and send them a traits packet informing them of the change qDebug() << "Overwriting avatar URL" << _avatar->getWireSafeSkeletonModelURL() << "to replacement" - << slaveSharedData.skeletonReplacementURL << "for" << sendingNode.getUUID(); - _avatar->setSkeletonModelURL(slaveSharedData.skeletonReplacementURL); + << workerSharedData.skeletonReplacementURL << "for" << sendingNode.getUUID(); + _avatar->setSkeletonModelURL(workerSharedData.skeletonReplacementURL); auto packet = NLPacket::create(PacketType::SetAvatarTraits, -1, true); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index e77eb4d070..ece5882590 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -36,7 +36,7 @@ const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps"; const QString OUTBOUND_AVATAR_TRAITS_STATS_KEY = "outbound_av_traits_kbps"; const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps"; -struct SlaveSharedData; +struct WorkerSharedData; class AvatarMixerClientData : public NodeData { Q_OBJECT @@ -47,7 +47,7 @@ public: using PerNodeTraitVersions = std::unordered_map; using NodeData::parseData; // Avoid clang warning about hiding. - int parseData(ReceivedMessage& message, const SlaveSharedData& SlaveSharedData); + int parseData(ReceivedMessage& message, const WorkerSharedData& WorkerSharedData); MixerAvatar& getAvatar() { return *_avatar; } const MixerAvatar& getAvatar() const { return *_avatar; } const MixerAvatar* getConstAvatarData() const { return _avatar.get(); } @@ -130,12 +130,12 @@ public: QVector& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; } void queuePacket(QSharedPointer message, SharedNodePointer node); - int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed + int processPackets(const WorkerSharedData& workerSharedData); // returns number of packets processed - void processSetTraitsMessage(ReceivedMessage& message, const SlaveSharedData& slaveSharedData, Node& sendingNode); + void processSetTraitsMessage(ReceivedMessage& message, const WorkerSharedData& workerSharedData, Node& sendingNode); void emulateDeleteEntitiesTraitsMessage(const QList& avatarEntityIDs); void processBulkAvatarTraitsAckMessage(ReceivedMessage& message); - void checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, Node& sendingNode, + void checkSkeletonURLAgainstAllowlist(const WorkerSharedData& workerSharedData, Node& sendingNode, AvatarTraits::TraitVersion traitVersion); using TraitsCheckTimestamp = std::chrono::steady_clock::time_point; diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerWorker.cpp similarity index 97% rename from assignment-client/src/avatars/AvatarMixerSlave.cpp rename to assignment-client/src/avatars/AvatarMixerWorker.cpp index 9a3ef3d0b5..d4a56e26ca 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerWorker.cpp @@ -1,5 +1,5 @@ // -// AvatarMixerSlave.cpp +// AvatarMixerWorker.cpp // assignment-client/src/avatar // // Created by Brad Hefta-Gaub on 2/14/2017. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AvatarMixerSlave.h" +#include "AvatarMixerWorker.h" #include #include @@ -36,12 +36,12 @@ namespace chrono = std::chrono; -void AvatarMixerSlave::configure(ConstIter begin, ConstIter end) { +void AvatarMixerWorker::configure(ConstIter begin, ConstIter end) { _begin = begin; _end = end; } -void AvatarMixerSlave::configureBroadcast(ConstIter begin, ConstIter end, +void AvatarMixerWorker::configureBroadcast(ConstIter begin, ConstIter end, p_high_resolution_clock::time_point lastFrameTimestamp, float maxKbpsPerNode, float throttlingRatio, float priorityReservedFraction) { @@ -53,13 +53,13 @@ void AvatarMixerSlave::configureBroadcast(ConstIter begin, ConstIter end, _avatarHeroFraction = priorityReservedFraction; } -void AvatarMixerSlave::harvestStats(AvatarMixerSlaveStats& stats) { +void AvatarMixerWorker::harvestStats(AvatarMixerWorkerStats& stats) { stats = _stats; _stats.reset(); } -void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { +void AvatarMixerWorker::processIncomingPackets(const SharedNodePointer& node) { auto start = usecTimestampNow(); auto nodeData = dynamic_cast(node->getLinkedData()); if (nodeData) { @@ -70,7 +70,7 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) { _stats.processIncomingPacketsElapsedTime += (end - start); } -int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) { +int AvatarMixerWorker::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) { if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) { QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious @@ -83,7 +83,7 @@ int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarM } } -qint64 AvatarMixerSlave::addTraitsNodeHeader(AvatarMixerClientData* listeningNodeData, +qint64 AvatarMixerWorker::addTraitsNodeHeader(AvatarMixerClientData* listeningNodeData, const AvatarMixerClientData* sendingNodeData, NLPacketList& traitsPacketList, qint64 bytesWritten) { @@ -98,7 +98,7 @@ qint64 AvatarMixerSlave::addTraitsNodeHeader(AvatarMixerClientData* listeningNod return bytesWritten; } -qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData, +qint64 AvatarMixerWorker::addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData, const AvatarMixerClientData* sendingNodeData, NLPacketList& traitsPacketList) { @@ -245,7 +245,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis return bytesWritten; } -int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) { +int AvatarMixerWorker::sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode) { if (AvatarMixer::shouldReplicateTo(agentNode, destinationNode)) { QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray(true); individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious @@ -262,7 +262,7 @@ int AvatarMixerSlave::sendReplicatedIdentityPacket(const Node& agentNode, const static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45; -void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { +void AvatarMixerWorker::broadcastAvatarData(const SharedNodePointer& node) { quint64 start = usecTimestampNow(); if ((node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) && node->getLinkedData() && node->getActiveSocket() && !node->isUpstream()) { @@ -311,7 +311,7 @@ namespace { } // Close anonymous namespace. -void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) { +void AvatarMixerWorker::broadcastAvatarDataToAgent(const SharedNodePointer& node) { const Node* destinationNode = node.data(); auto nodeList = DependencyManager::get(); @@ -680,7 +680,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) uint64_t REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US = 5 * 1000 * 1000; -void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node) { +void AvatarMixerWorker::broadcastAvatarDataToDownstreamMixer(const SharedNodePointer& node) { _stats.downstreamMixersBroadcastedTo++; AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); diff --git a/assignment-client/src/avatars/AvatarMixerSlave.h b/assignment-client/src/avatars/AvatarMixerWorker.h similarity index 90% rename from assignment-client/src/avatars/AvatarMixerSlave.h rename to assignment-client/src/avatars/AvatarMixerWorker.h index f14e50e11f..fe1877c078 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.h +++ b/assignment-client/src/avatars/AvatarMixerWorker.h @@ -1,5 +1,5 @@ // -// AvatarMixerSlave.h +// AvatarMixerWorker.h // assignment-client/src/avatar // // Created by Brad Hefta-Gaub on 2/14/2017. @@ -9,14 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AvatarMixerSlave_h -#define hifi_AvatarMixerSlave_h +#ifndef hifi_AvatarMixerWorker_h +#define hifi_AvatarMixerWorker_h #include class AvatarMixerClientData; -class AvatarMixerSlaveStats { +class AvatarMixerWorkerStats { public: int nodesProcessed { 0 }; int packetsProcessed { 0 }; @@ -67,7 +67,7 @@ public: jobElapsedTime = 0; } - AvatarMixerSlaveStats& operator+=(const AvatarMixerSlaveStats& rhs) { + AvatarMixerWorkerStats& operator+=(const AvatarMixerWorkerStats& rhs) { nodesProcessed += rhs.nodesProcessed; packetsProcessed += rhs.packetsProcessed; processIncomingPacketsElapsedTime += rhs.processIncomingPacketsElapsedTime; @@ -96,15 +96,15 @@ public: class EntityTree; using EntityTreePointer = std::shared_ptr; -struct SlaveSharedData { - QStringList skeletonURLWhitelist; +struct WorkerSharedData { + QStringList skeletonURLAllowlist; QUrl skeletonReplacementURL; EntityTreePointer entityTree; }; -class AvatarMixerSlave { +class AvatarMixerWorker { public: - AvatarMixerSlave(SlaveSharedData* sharedData) : _sharedData(sharedData) {}; + AvatarMixerWorker(WorkerSharedData* sharedData) : _sharedData(sharedData) {}; using ConstIter = NodeList::const_iterator; void configure(ConstIter begin, ConstIter end); @@ -116,7 +116,7 @@ public: void processIncomingPackets(const SharedNodePointer& node); void broadcastAvatarData(const SharedNodePointer& node); - void harvestStats(AvatarMixerSlaveStats& stats); + void harvestStats(AvatarMixerWorkerStats& stats); private: int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode); @@ -143,8 +143,8 @@ private: float _throttlingRatio { 0.0f }; float _avatarHeroFraction { 0.4f }; - AvatarMixerSlaveStats _stats; - SlaveSharedData* _sharedData; + AvatarMixerWorkerStats _stats; + WorkerSharedData* _sharedData; }; -#endif // hifi_AvatarMixerSlave_h +#endif // hifi_AvatarMixerWorker_h diff --git a/assignment-client/src/avatars/AvatarMixerSlavePool.cpp b/assignment-client/src/avatars/AvatarMixerWorkerPool.cpp similarity index 63% rename from assignment-client/src/avatars/AvatarMixerSlavePool.cpp rename to assignment-client/src/avatars/AvatarMixerWorkerPool.cpp index 027e68e88b..913278da4f 100644 --- a/assignment-client/src/avatars/AvatarMixerSlavePool.cpp +++ b/assignment-client/src/avatars/AvatarMixerWorkerPool.cpp @@ -1,5 +1,5 @@ // -// AvatarMixerSlavePool.cpp +// AvatarMixerWorkerPool.cpp // assignment-client/src/avatar // // Created by Brad Hefta-Gaub on 2/14/2017. @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "AvatarMixerSlavePool.h" +#include "AvatarMixerWorkerPool.h" #include #include -void AvatarMixerSlaveThread::run() { +void AvatarMixerWorkerThread::run() { while (true) { wait(); @@ -32,10 +32,10 @@ void AvatarMixerSlaveThread::run() { } } -void AvatarMixerSlaveThread::wait() { +void AvatarMixerWorkerThread::wait() { { Lock lock(_pool._mutex); - _pool._slaveCondition.wait(lock, [&] { + _pool._workerCondition.wait(lock, [&] { assert(_pool._numStarted <= _pool._numThreads); return _pool._numStarted != _pool._numThreads; }); @@ -47,7 +47,7 @@ void AvatarMixerSlaveThread::wait() { _function = _pool._function; } -void AvatarMixerSlaveThread::notify(bool stopping) { +void AvatarMixerWorkerThread::notify(bool stopping) { { Lock lock(_pool._mutex); assert(_pool._numFinished < _pool._numThreads); @@ -59,30 +59,30 @@ void AvatarMixerSlaveThread::notify(bool stopping) { _pool._poolCondition.notify_one(); } -bool AvatarMixerSlaveThread::try_pop(SharedNodePointer& node) { +bool AvatarMixerWorkerThread::try_pop(SharedNodePointer& node) { return _pool._queue.try_pop(node); } -void AvatarMixerSlavePool::processIncomingPackets(ConstIter begin, ConstIter end) { - _function = &AvatarMixerSlave::processIncomingPackets; - _configure = [=](AvatarMixerSlave& slave) { - slave.configure(begin, end); +void AvatarMixerWorkerPool::processIncomingPackets(ConstIter begin, ConstIter end) { + _function = &AvatarMixerWorker::processIncomingPackets; + _configure = [=](AvatarMixerWorker& worker) { + worker.configure(begin, end); }; run(begin, end); } -void AvatarMixerSlavePool::broadcastAvatarData(ConstIter begin, ConstIter end, +void AvatarMixerWorkerPool::broadcastAvatarData(ConstIter begin, ConstIter end, p_high_resolution_clock::time_point lastFrameTimestamp, float maxKbpsPerNode, float throttlingRatio) { - _function = &AvatarMixerSlave::broadcastAvatarData; - _configure = [=](AvatarMixerSlave& slave) { - slave.configureBroadcast(begin, end, lastFrameTimestamp, maxKbpsPerNode, throttlingRatio, + _function = &AvatarMixerWorker::broadcastAvatarData; + _configure = [=](AvatarMixerWorker& worker) { + worker.configureBroadcast(begin, end, lastFrameTimestamp, maxKbpsPerNode, throttlingRatio, _priorityReservedFraction); }; run(begin, end); } -void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) { +void AvatarMixerWorkerPool::run(ConstIter begin, ConstIter end) { _begin = begin; _end = end; @@ -96,7 +96,7 @@ void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) { // run _numStarted = _numFinished = 0; - _slaveCondition.notify_all(); + _workerCondition.notify_all(); // wait _poolCondition.wait(lock, [&] { @@ -111,17 +111,17 @@ void AvatarMixerSlavePool::run(ConstIter begin, ConstIter end) { } -void AvatarMixerSlavePool::each(std::function functor) { - for (auto& slave : _slaves) { - functor(*slave.get()); +void AvatarMixerWorkerPool::each(std::function functor) { + for (auto& worker : _workers) { + functor(*worker.get()); } } #ifdef DEBUG_EVENT_QUEUE -void AvatarMixerSlavePool::queueStats(QJsonObject& stats) { +void AvatarMixerWorkerPool::queueStats(QJsonObject& stats) { unsigned i = 0; - for (auto& slave : _slaves) { - int queueSize = ::hifi::qt::getEventQueueSize(slave.get()); + for (auto& worker : _workers) { + int queueSize = ::hifi::qt::getEventQueueSize(worker.get()); QString queueName = QString("avatar_thread_event_queue_%1").arg(i); stats[queueName] = queueSize; @@ -130,7 +130,7 @@ void AvatarMixerSlavePool::queueStats(QJsonObject& stats) { } #endif // DEBUG_EVENT_QUEUE -void AvatarMixerSlavePool::setNumThreads(int numThreads) { +void AvatarMixerWorkerPool::setNumThreads(int numThreads) { // clamp to allowed size { int maxThreads = QThread::idealThreadCount(); @@ -150,35 +150,35 @@ void AvatarMixerSlavePool::setNumThreads(int numThreads) { resize(numThreads); } -void AvatarMixerSlavePool::resize(int numThreads) { - assert(_numThreads == (int)_slaves.size()); +void AvatarMixerWorkerPool::resize(int numThreads) { + assert(_numThreads == (int)_workers.size()); qDebug("%s: set %d threads (was %d)", __FUNCTION__, numThreads, _numThreads); Lock lock(_mutex); if (numThreads > _numThreads) { - // start new slaves + // start new workers for (int i = 0; i < numThreads - _numThreads; ++i) { - auto slave = new AvatarMixerSlaveThread(*this, _slaveSharedData); - slave->start(); - _slaves.emplace_back(slave); + auto worker = new AvatarMixerWorkerThread(*this, _workerSharedData); + worker->start(); + _workers.emplace_back(worker); } } else if (numThreads < _numThreads) { - auto extraBegin = _slaves.begin() + numThreads; + auto extraBegin = _workers.begin() + numThreads; - // mark slaves to stop... - auto slave = extraBegin; - while (slave != _slaves.end()) { - (*slave)->_stop = true; - ++slave; + // mark workers to stop... + auto worker = extraBegin; + while (worker != _workers.end()) { + (*worker)->_stop = true; + ++worker; } // ...cycle them until they do stop... _numStopped = 0; while (_numStopped != (_numThreads - numThreads)) { _numStarted = _numFinished = _numStopped; - _slaveCondition.notify_all(); + _workerCondition.notify_all(); _poolCondition.wait(lock, [&] { assert(_numFinished <= _numThreads); return _numFinished == _numThreads; @@ -186,18 +186,18 @@ void AvatarMixerSlavePool::resize(int numThreads) { } // ...wait for threads to finish... - slave = extraBegin; - while (slave != _slaves.end()) { - QThread* thread = reinterpret_cast(slave->get()); + worker = extraBegin; + while (worker != _workers.end()) { + QThread* thread = reinterpret_cast(worker->get()); static const int MAX_THREAD_WAIT_TIME = 10; thread->wait(MAX_THREAD_WAIT_TIME); - ++slave; + ++worker; } // ...and erase them - _slaves.erase(extraBegin, _slaves.end()); + _workers.erase(extraBegin, _workers.end()); } _numThreads = _numStarted = _numFinished = numThreads; - assert(_numThreads == (int)_slaves.size()); + assert(_numThreads == (int)_workers.size()); } diff --git a/assignment-client/src/avatars/AvatarMixerSlavePool.h b/assignment-client/src/avatars/AvatarMixerWorkerPool.h similarity index 56% rename from assignment-client/src/avatars/AvatarMixerSlavePool.h rename to assignment-client/src/avatars/AvatarMixerWorkerPool.h index 915c6d8dc4..1c7a4a9baf 100644 --- a/assignment-client/src/avatars/AvatarMixerSlavePool.h +++ b/assignment-client/src/avatars/AvatarMixerWorkerPool.h @@ -1,5 +1,5 @@ // -// AvatarMixerSlavePool.h +// AvatarMixerWorkerPool.h // assignment-client/src/avatar // // Created by Brad Hefta-Gaub on 2/14/2017. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_AvatarMixerSlavePool_h -#define hifi_AvatarMixerSlavePool_h +#ifndef hifi_AvatarMixerWorkerPool_h +#define hifi_AvatarMixerWorkerPool_h #include #include @@ -22,38 +22,38 @@ #include #include -#include "AvatarMixerSlave.h" +#include "AvatarMixerWorker.h" -class AvatarMixerSlavePool; +class AvatarMixerWorkerPool; -class AvatarMixerSlaveThread : public QThread, public AvatarMixerSlave { +class AvatarMixerWorkerThread : public QThread, public AvatarMixerWorker { Q_OBJECT using ConstIter = NodeList::const_iterator; using Mutex = std::mutex; using Lock = std::unique_lock; public: - AvatarMixerSlaveThread(AvatarMixerSlavePool& pool, SlaveSharedData* slaveSharedData) : - AvatarMixerSlave(slaveSharedData), _pool(pool) {}; + AvatarMixerWorkerThread(AvatarMixerWorkerPool& pool, WorkerSharedData* workerSharedData) : + AvatarMixerWorker(workerSharedData), _pool(pool) {}; void run() override final; private: - friend class AvatarMixerSlavePool; + friend class AvatarMixerWorkerPool; void wait(); void notify(bool stopping); bool try_pop(SharedNodePointer& node); - AvatarMixerSlavePool& _pool; - void (AvatarMixerSlave::*_function)(const SharedNodePointer& node) { nullptr }; + AvatarMixerWorkerPool& _pool; + void (AvatarMixerWorker::*_function)(const SharedNodePointer& node) { nullptr }; bool _stop { false }; }; -// Slave pool for avatar mixers -// AvatarMixerSlavePool is not thread-safe! It should be instantiated and used from a single thread. -class AvatarMixerSlavePool { +// Worker pool for avatar mixers +// AvatarMixerWorkerPool is not thread-safe! It should be instantiated and used from a single thread. +class AvatarMixerWorkerPool { using Queue = tbb::concurrent_queue; using Mutex = std::mutex; using Lock = std::unique_lock; @@ -62,17 +62,17 @@ class AvatarMixerSlavePool { public: using ConstIter = NodeList::const_iterator; - AvatarMixerSlavePool(SlaveSharedData* slaveSharedData, int numThreads = QThread::idealThreadCount()) : - _slaveSharedData(slaveSharedData) { setNumThreads(numThreads); } - ~AvatarMixerSlavePool() { resize(0); } + AvatarMixerWorkerPool(WorkerSharedData* workerSharedData, int numThreads = QThread::idealThreadCount()) : + _workerSharedData(workerSharedData) { setNumThreads(numThreads); } + ~AvatarMixerWorkerPool() { resize(0); } - // Jobs the slave pool can do... + // Jobs the worker pool can do... void processIncomingPackets(ConstIter begin, ConstIter end); void broadcastAvatarData(ConstIter begin, ConstIter end, p_high_resolution_clock::time_point lastFrameTimestamp, float maxKbpsPerNode, float throttlingRatio); - // iterate over all slaves - void each(std::function functor); + // iterate over all workers + void each(std::function functor); #ifdef DEBUG_EVENT_QUEUE void queueStats(QJsonObject& stats); @@ -88,18 +88,18 @@ private: void run(ConstIter begin, ConstIter end); void resize(int numThreads); - std::vector> _slaves; + std::vector> _workers; - friend void AvatarMixerSlaveThread::wait(); - friend void AvatarMixerSlaveThread::notify(bool stopping); - friend bool AvatarMixerSlaveThread::try_pop(SharedNodePointer& node); + friend void AvatarMixerWorkerThread::wait(); + friend void AvatarMixerWorkerThread::notify(bool stopping); + friend bool AvatarMixerWorkerThread::try_pop(SharedNodePointer& node); // synchronization state Mutex _mutex; - ConditionVariable _slaveCondition; + ConditionVariable _workerCondition; ConditionVariable _poolCondition; - void (AvatarMixerSlave::*_function)(const SharedNodePointer& node); - std::function _configure; + void (AvatarMixerWorker::*_function)(const SharedNodePointer& node); + std::function _configure; // Set from Domain Settings: float _priorityReservedFraction { 0.4f }; @@ -114,7 +114,7 @@ private: ConstIter _begin; ConstIter _end; - SlaveSharedData* _slaveSharedData; + WorkerSharedData* _workerSharedData; }; -#endif // hifi_AvatarMixerSlavePool_h +#endif // hifi_AvatarMixerWorkerPool_h diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index d27a69ff7c..ea3ebd07f6 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -320,11 +320,11 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio tree->setWantEditLogging(wantEditLogging); tree->setWantTerseEditLogging(wantTerseEditLogging); - QString entityScriptSourceWhitelist; - if (readOptionString("entityScriptSourceWhitelist", settingsSectionObject, entityScriptSourceWhitelist)) { - tree->setEntityScriptSourceWhitelist(entityScriptSourceWhitelist); + QString entityScriptSourceAllowlist; + if (readOptionString("entityScriptSourceAllowlist", settingsSectionObject, entityScriptSourceAllowlist)) { + tree->setEntityScriptSourceAllowlist(entityScriptSourceAllowlist); } else { - tree->setEntityScriptSourceWhitelist(""); + tree->setEntityScriptSourceAllowlist(""); } auto entityEditFilters = DependencyManager::get(); diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake index 8e873738b5..564475f406 100644 --- a/cmake/macros/GenerateInstallers.cmake +++ b/cmake/macros/GenerateInstallers.cmake @@ -5,7 +5,7 @@ # Created by Leonardo Murillo on 12/16/2015. # Copyright 2015 High Fidelity, Inc. # Copyright 2021 Vircadia contributors. -# Copyright 2022 Overte e.V. +# Copyright 2022-2024 Overte e.V. # # Distributed under the Apache License, Version 2.0. # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -33,8 +33,7 @@ macro(GENERATE_INSTALLERS) set(CPACK_PACKAGE_NAME ${_DISPLAY_NAME}) set(CPACK_PACKAGE_VENDOR "Overte") set(CPACK_PACKAGE_VERSION ${BUILD_VERSION}) - # There is some sort of bug which adds a "-" between the BUILD_VERSION and the RELEASE_NAME. - set(CPACK_PACKAGE_FILE_NAME "Overte${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}${RELEASE_NAME}") + set(CPACK_PACKAGE_FILE_NAME "Overte${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}") set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME}) set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME}) set(CPACK_NSIS_COMPRESSOR "LZMA") diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 4d2cac7b3e..4320522784 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -26,7 +26,7 @@ macro(SET_PACKAGING_PARAMETERS) set_from_env(STABLE_BUILD STABLE_BUILD 0) set_from_env(PRELOADED_STARTUP_LOCATION PRELOADED_STARTUP_LOCATION "") - set_from_env(PRELOADED_SCRIPT_WHITELIST PRELOADED_SCRIPT_WHITELIST "") + set_from_env(PRELOADED_SCRIPT_ALLOWLIST PRELOADED_SCRIPT_ALLOWLIST "") set_from_env(BYPASS_SIGNING BYPASS_SIGNING 0) diff --git a/cmake/ports/webrtc/README.md b/cmake/ports/webrtc/README.md index 398d6e7e04..79b79eff0d 100644 --- a/cmake/ports/webrtc/README.md +++ b/cmake/ports/webrtc/README.md @@ -180,6 +180,8 @@ Also use the path in the `gn gen` commands, below, making sure to escape `\`s as Use a VS2019 developer command prompt in the *src* directory. +If it complains about the debugger being missing from your Windows SDK, modify your Windows "Software Development Kit" in your installed programs (See: https://stackoverflow.com/questions/46237620/how-to-install-debugging-tools-with-visual-studio-2017-installer). + Create a release build of the WebRTC library: - `gn gen --ide=vs2019 out\Release --filters=//:webrtc "--args=is_debug=false is_clang=false use_custom_libcxx=false libcxx_is_shared=true symbol_level=2 use_lld=false rtc_include_tests=false rtc_build_tools=false rtc_build_examples=false proprietary_codecs=true rtc_use_h264=true enable_libaom=false rtc_enable_protobuf=false rtc_build_ssl=false rtc_ssl_root=\"\""` - `ninja -C out\Release` diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 25541efb17..132664c99a 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -29,7 +29,7 @@ namespace BuildInfo { const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; const QString BUILD_TIME = "@BUILD_TIME@"; const QString PRELOADED_STARTUP_LOCATION = "@PRELOADED_STARTUP_LOCATION@"; - const QString PRELOADED_SCRIPT_WHITELIST = "@PRELOADED_SCRIPT_WHITELIST@"; + const QString PRELOADED_SCRIPT_ALLOWLIST = "@PRELOADED_SCRIPT_ALLOWLIST@"; enum BuildType { Dev, diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index ae5397770b..68897dee2c 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -1207,53 +1207,8 @@ Section "-Core installation" ; 2016-02-25 - The following delete blocks are temporary and can be removed once users who had the initial installer have updated ; 2019-09-10 - (3 and a half years later) Sure they are buddy. Sure they are. - ; MessageBox MB_OK|MB_ICONEXCLAMATION "installer type is @INSTALLER_TYPE@" - - ;Delete any server executables that might have been installed by bad versions of the client-only installer, but ONLY if we are a client-only installer - ${If} "@INSTALLER_TYPE@" == "client_only" - ; MessageBox MB_OK|MB_ICONEXCLAMATION "trying to delete server binaries" - Delete "$INSTDIR\assignment-client.exe" - Delete "$INSTDIR\domain-server.exe" - ${EndIf} - - ;Delete any server-console files installed before it was placed in sub-folder - Delete "$INSTDIR\server-console.exe" - RMDir /r "$INSTDIR\locales" - RMDir /r "$INSTDIR\resources\app" - RMDir /r "$INSTDIR\client" - Delete "$INSTDIR\resources\atom.asar" - Delete "$INSTDIR\build-info.json" - Delete "$INSTDIR\content_resources_200_percent.pak" - Delete "$INSTDIR\content_shell.pak" - Delete "$INSTDIR\LICENSE" - Delete "$INSTDIR\LICENSES.chromium.html" - Delete "$INSTDIR\natives_blob.bin" - Delete "$INSTDIR\node.dll" - Delete "$INSTDIR\pdf.dll" - Delete "$INSTDIR\snapshot_blob.bin" - Delete "$INSTDIR\ui_resources_200_percent.pak" - Delete "$INSTDIR\vccorlib120.dll" - Delete "$INSTDIR\version" - Delete "$INSTDIR\xinput1_3.dll" - - ; Delete old desktop shortcuts before they were renamed during Sandbox rename - Delete "$DESKTOP\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk" - Delete "$DESKTOP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk" - - ; Delete old Start Menu shortcuts before Sandbox rename - Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk" - Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk" - - ; Delete old startup item for Server Console before Sandbox rename - SetShellVarContext current - Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk" - SetShellVarContext all - - ; Rename the incorrectly cased Raleway font - Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml" - - ; Remove the Old Interface directory and vcredist_x64.exe (from installs prior to Server Console) - RMDir /r "$INSTDIR\Interface" + ; Delete old hifiNeuron.dll, since we dropped support for it and it causes a crash on startup. + Delete "$INSTDIR\plugins\hifiNeuron.dll" ;Use the entire tree produced by the INSTALL target. Keep the ;list of directories here in sync with the RMDir commands below. diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index ff5ae875bc..75fdcc6db4 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -178,7 +178,7 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin } // If this user is a known member of a domain group, give them the implied permissions. - // Do before processing verifiedUsername in case user is logged into the Directory Services and is a member of a blacklist group. + // Do before processing verifiedUsername in case user is logged into the Directory Services and is a member of a blocklist group. if (!verifiedDomainUserName.isEmpty()) { auto userGroups = _domainGroupMemberships[verifiedDomainUserName]; foreach (QString userGroup, userGroups) { @@ -277,8 +277,8 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin } } - // if this user is a known member of a blacklist group, remove the implied permissions - foreach (QUuid groupID, _server->_settingsManager.getBlacklistGroupIDs()) { + // if this user is a known member of a blocklist group, remove the implied permissions + foreach (QUuid groupID, _server->_settingsManager.getBlocklistGroupIDs()) { QUuid rankID = _server->_settingsManager.isGroupMember(verifiedUsername, groupID); if (rankID != QUuid()) { QUuid rankID = _server->_settingsManager.isGroupMember(verifiedUsername, groupID); @@ -287,7 +287,7 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin GroupRank rank = _server->_settingsManager.getGroupRank(groupID, rankID); #ifdef WANT_DEBUG - qDebug() << "| user-permissions: user is in blacklist group:" << groupID << " rank:" << rank.name + qDebug() << "| user-permissions: user is in blocklist group:" << groupID << " rank:" << rank.name << "so:" << userPerms; #endif } @@ -299,20 +299,20 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin userPerms.setVerifiedUserName(verifiedUsername); } - // If this user is a known member of an domain group that is blacklisted, remove the implied permissions. + // If this user is a known member of an domain group that is blocklisted, remove the implied permissions. if (!verifiedDomainUserName.isEmpty()) { auto userGroups = _domainGroupMemberships[verifiedDomainUserName]; foreach(QString userGroup, userGroups) { // A domain group is signified by a leading special character, "@". // Multiple domain groups may be specified in one domain server setting as a comma- and/or space-separated lists of // domain group names. For example, "@silver @Gold, @platinum". - auto domainGroups = _server->_settingsManager.getDomainServerBlacklistGroupNames() + auto domainGroups = _server->_settingsManager.getDomainServerBlocklistGroupNames() .filter(QRegularExpression("^(.*[\\s,])?" + QRegularExpression::escape(userGroup) + "([\\s,].*)?$", QRegularExpression::CaseInsensitiveOption)); foreach(QString domainGroup, domainGroups) { userPerms &= ~_server->_settingsManager.getForbiddensForGroup(domainGroup, QUuid()); #ifdef WANT_DEBUG - qDebug() << "| user-permissions: domain user is in blacklist group:" << domainGroup << "so:" << userPerms; + qDebug() << "| user-permissions: domain user is in blocklist group:" << domainGroup << "so:" << userPerms; #endif } } @@ -1027,7 +1027,7 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { QJsonObject json; QSet groupIDSet; - foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlacklistGroupIDs()) { + foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlocklistGroupIDs()) { groupIDSet += groupID.toString().mid(1,36); } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 7d9456f059..5db7bb7f74 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -341,17 +341,17 @@ DomainServer::DomainServer(int argc, char* argv[]) : connect(&_settingsManager, &DomainServerSettingsManager::updateNodePermissions, [this] { _metadata->securityChanged(true); }); qDebug() << "domain-server is running"; - static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist"; + static const QString AC_SUBNET_ALLOWLIST_SETTING_PATH = "security.ac_subnet_allowlist"; static const Subnet LOCALHOST { QHostAddress("127.0.0.1"), 32 }; - _acSubnetWhitelist = { LOCALHOST }; + _acSubnetAllowlist = { LOCALHOST }; - auto whitelist = _settingsManager.valueOrDefaultValueForKeyPath(AC_SUBNET_WHITELIST_SETTING_PATH).toStringList(); - for (auto& subnet : whitelist) { + auto allowlist = _settingsManager.valueOrDefaultValueForKeyPath(AC_SUBNET_ALLOWLIST_SETTING_PATH).toStringList(); + for (auto& subnet : allowlist) { auto netmaskParts = subnet.trimmed().split("/"); if (netmaskParts.size() > 2) { - qDebug() << "Ignoring subnet in whitelist, malformed: " << subnet; + qDebug() << "Ignoring subnet in allowlist, malformed: " << subnet; continue; } @@ -363,7 +363,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : bool ok; netmask = netmaskParts[1].toInt(&ok); if (!ok) { - qDebug() << "Ignoring subnet in whitelist, bad netmask: " << subnet; + qDebug() << "Ignoring subnet in allowlist, bad netmask: " << subnet; continue; } } @@ -371,10 +371,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : auto ip = QHostAddress(netmaskParts[0]); if (!ip.isNull()) { - qDebug() << "Adding AC whitelist subnet: " << subnet << " -> " << (ip.toString() + "/" + QString::number(netmask)); - _acSubnetWhitelist.push_back({ ip , netmask }); + qDebug() << "Adding AC allowlist subnet: " << subnet << " -> " << (ip.toString() + "/" + QString::number(netmask)); + _acSubnetAllowlist.push_back({ ip , netmask }); } else { - qDebug() << "Ignoring subnet in whitelist, invalid ip portion: " << subnet; + qDebug() << "Ignoring subnet in allowlist, invalid ip portion: " << subnet; } } @@ -1502,8 +1502,8 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer _replicatedUsernames; diff --git a/domain-server/src/DomainServerExporter.cpp b/domain-server/src/DomainServerExporter.cpp index a7affaf4dd..8640ca3a5c 100644 --- a/domain-server/src/DomainServerExporter.cpp +++ b/domain-server/src/DomainServerExporter.cpp @@ -172,20 +172,20 @@ static const QMap TYPE_MAP { { "avatar_mixer_single_core_tasks_process_events" , DomainServerExporter::MetricType::Counter }, { "avatar_mixer_single_core_tasks_queue_incoming_packet" , DomainServerExporter::MetricType::Gauge }, { "avatar_mixer_single_core_tasks_send_stats" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_received_1_nodes_processed" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_1_nodes_broadcasted_to" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_2_average_others_included" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_3_average_over_budget_avatars" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_4_average_data_bytes" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_5_average_traits_bytes" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_6_average_identity_bytes" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_sent_7_average_hero_avatars" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_1_process_incoming_packets" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_2_ignore_calculation" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_3_to_byte_array" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_4_avatar_data_packing" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_5_packet_sending" , DomainServerExporter::MetricType::Gauge }, - { "avatar_mixer_slaves_aggregate_per_frame_timing_6_job_elapsed_time" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_received_1_nodes_processed" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_1_nodes_broadcasted_to" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_2_average_others_included" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_3_average_over_budget_avatars" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_4_average_data_bytes" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_5_average_traits_bytes" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_6_average_identity_bytes" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_sent_7_average_hero_avatars" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_1_process_incoming_packets" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_2_ignore_calculation" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_3_to_byte_array" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_4_avatar_data_packing" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_5_packet_sending" , DomainServerExporter::MetricType::Gauge }, + { "avatar_mixer_workers_aggregate_per_frame_timing_6_job_elapsed_time" , DomainServerExporter::MetricType::Gauge }, { "avatar_mixer_threads" , DomainServerExporter::MetricType::Gauge }, { "avatar_mixer_throttling_ratio" , DomainServerExporter::MetricType::Gauge }, { "avatar_mixer_trailing_mix_ratio" , DomainServerExporter::MetricType::Gauge }, @@ -254,9 +254,9 @@ static const QMap TYPE_MAP { // // For numeric values with an unit, instead of trying to parse it, the stats will just need to // have a second copy of the metric added, with the value expressed as a number, with the original -// being blacklisted here. +// being blocklisted here. -static const QSet BLACKLIST = { +static const QSet BLOCKLIST = { "asset_server_connection_stats_last_heard", // Timestamp as a string "asset_server_username", // Username "audio_mixer_listeners_jitter_downstream_avg_gap", // Number as string with unit name, alternative added @@ -379,7 +379,7 @@ void DomainServerExporter::generateMetricsFromJson(QTextStream& stream, continue; } - if (BLACKLIST.contains(metricName)) { + if (BLOCKLIST.contains(metricName)) { continue; } diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index bcea7f0e01..fe13c29df2 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -688,7 +688,7 @@ void DomainServerSettingsManager::packPermissions() { // save settings for groups packPermissionsForMap("permissions", _groupPermissions, GROUP_PERMISSIONS_KEYPATH); - // save settings for blacklist groups + // save settings for blocklist groups packPermissionsForMap("permissions", _groupForbiddens, GROUP_FORBIDDENS_KEYPATH); persistToFile(); @@ -869,7 +869,7 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() { } } - QList forbiddenGroupIDs = getBlacklistGroupIDs(); + QList forbiddenGroupIDs = getBlocklistGroupIDs(); foreach (QUuid groupID, forbiddenGroupIDs) { QString groupName = _groupNames[groupID]; QHash& ranksForGroup = _groupRanks[groupID]; @@ -1743,7 +1743,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ QJsonObject postedObject(postedSettingsObject); static const QString SECURITY_ROOT_KEY = "security"; - static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist"; + static const QString AC_SUBNET_ALLOWLIST_KEY = "ac_subnet_allowlist"; static const QString BROADCASTING_KEY = "broadcasting"; static const QString WIZARD_KEY = "wizard"; static const QString DESCRIPTION_ROOT_KEY = "descriptors"; @@ -1863,7 +1863,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != DESCRIPTION_ROOT_KEY && rootKey != WIZARD_KEY) || - settingKey == AC_SUBNET_WHITELIST_KEY) { + settingKey == AC_SUBNET_ALLOWLIST_KEY) { needRestart = true; } } else { @@ -2038,7 +2038,7 @@ void DomainServerSettingsManager::apiRefreshGroupInformation() { } if (_groupIDs.contains(lowerGroupName)) { // we already know about this one. recall setGroupID in case the group has been - // added to another section (the same group is found in both groups and blacklists). + // added to another section (the same group is found in both groups and blocklists). changed = setGroupID(groupName, _groupIDs[lowerGroupName]); continue; } @@ -2245,7 +2245,7 @@ QList DomainServerSettingsManager::getGroupIDs() { return result.values(); } -QList DomainServerSettingsManager::getBlacklistGroupIDs() { +QList DomainServerSettingsManager::getBlocklistGroupIDs() { QSet result; foreach (NodePermissionsKey groupKey, _groupForbiddens.keys()) { if (_groupForbiddens[groupKey]->isGroup()) { @@ -2264,7 +2264,7 @@ QStringList DomainServerSettingsManager::getDomainServerGroupNames() { return result.values(); } -QStringList DomainServerSettingsManager::getDomainServerBlacklistGroupNames() { +QStringList DomainServerSettingsManager::getDomainServerBlocklistGroupNames() { // All names as listed in the domain server settings; not necessarily Directory Services groups. QSet result; foreach (NodePermissionsKey groupKey, _groupForbiddens.keys()) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 6f23737059..3c7959291c 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -135,10 +135,10 @@ public: GroupRank getGroupRank(QUuid groupID, QUuid rankID) { return _groupRanks[groupID][rankID]; } QList getGroupIDs(); - QList getBlacklistGroupIDs(); + QList getBlocklistGroupIDs(); QStringList getDomainServerGroupNames(); - QStringList getDomainServerBlacklistGroupNames(); + QStringList getDomainServerBlocklistGroupNames(); // these are used to locally cache the result of calling "/api/v1/groups/.../is_member/..." on Directory Services api void clearGroupMemberships(const QString& name) { _groupMembership[name.toLower()].clear(); } diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 4dc9268980..ff1549ab1e 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -101,7 +101,7 @@ endif() if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat'), '-disableMetrics' ] - self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/vcpkg-windows_x86_64_2023.10.19.zip' + self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/vcpkg-windows_x86_64_2024.06.15.zip' self.vcpkgHash = 'f335234f0722c15376fb10747f558c18c83a3e1e3b6565cf0dabfb18c9625a99234d054457fd05190c0ecd7a59ca43305bc93b50dbf764a4e1f567a15168d051' self.hostTriplet = 'x64-windows' if usePrebuilt: diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index 04af9eadc9..1c8250cfa8 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -4,6 +4,7 @@ // Created by Wayne Chen on 10/18/18 // Copyright 2018 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. +// Copyright 2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -377,13 +378,13 @@ Item { } } - function onHandleLoginCompleted(): { + function onHandleLoginCompleted() { console.log("Login Succeeded"); loggingInBody.loadingSuccess(); } function onHandleLoginFailed() { - console.log("Login Failed") + console.log("Login Failed"); loggingInSpinner.visible = false; loggingInGlyph.visible = false; var errorString = ""; diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 0f7d521653..7bfdf02889 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -354,7 +354,7 @@ Rectangle { font: avatarGainSliderText.font } RalewayRegular { - // The slider for my card is special, it controls the master gain + // The slider for my card is special, it controls the primary gain id: avatarGainSliderText; text: "People volume"; size: 16; @@ -645,7 +645,7 @@ Rectangle { font: noiseReductionThresholdSliderText.font } RalewayRegular { - // The slider for my card is special, it controls the master gain + // The slider for my card is special, it controls the primary gain id: noiseReductionThresholdSliderText; text: "Audio input threshold"; size: 16; diff --git a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml index cac6ab6865..1ac2c878bb 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAboutDialog.qml @@ -4,6 +4,7 @@ // Created by David Rowe on 18 Apr 2017 // Copyright 2017 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. +// Copyright 2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -39,7 +40,7 @@ Rectangle { color: "white" } RalewayRegular { - text: "Build " + About.buildVersion + " " + About.releaseName + text: "Build " + About.buildVersion size: 16 color: "white" } diff --git a/interface/resources/qml/hifi/dialogs/security/EntityScriptQMLWhitelist.qml b/interface/resources/qml/hifi/dialogs/security/EntityScriptQMLAllowlist.qml similarity index 77% rename from interface/resources/qml/hifi/dialogs/security/EntityScriptQMLWhitelist.qml rename to interface/resources/qml/hifi/dialogs/security/EntityScriptQMLAllowlist.qml index 8180475527..c23233d617 100644 --- a/interface/resources/qml/hifi/dialogs/security/EntityScriptQMLWhitelist.qml +++ b/interface/resources/qml/hifi/dialogs/security/EntityScriptQMLAllowlist.qml @@ -1,5 +1,5 @@ // -// EntityScriptQMLWhitelist.qml +// EntityScriptQMLAllowlist.qml // interface/resources/qml/hifi/dialogs/security // // Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com @@ -8,7 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// Security Settings for the Entity Script QML Whitelist +// Security Settings for the Entity Script QML Allowlist import Hifi 1.0 as Hifi import QtQuick 2.8 @@ -23,25 +23,25 @@ import "../../../windows" Rectangle { id: parentBody; - function getWhitelistAsText() { - var whitelist = Settings.getValue("private/settingsSafeURLS"); - var arrayWhitelist = whitelist.split(",").join("\n"); - return arrayWhitelist; + function getAllowlistAsText() { + var allowlist = Settings.getValue("private/settingsSafeURLS"); + var arrayAllowlist = allowlist.split(",").join("\n"); + return arrayAllowlist; } - function setWhitelistAsText(whitelistText) { - Settings.setValue("private/settingsSafeURLS", whitelistText.text); + function setAllowlistAsText(allowlistText) { + Settings.setValue("private/settingsSafeURLS", allowlistText.text); - var originalSetString = whitelistText.text; + var originalSetString = allowlistText.text; var originalSet = originalSetString.split(' ').join(''); var check = Settings.getValue("private/settingsSafeURLS"); var arrayCheck = check.split(",").join("\n"); - setWhitelistSuccess(arrayCheck === originalSet); + setAllowlistSuccess(arrayCheck === originalSet); } - function setWhitelistSuccess(success) { + function setAllowlistSuccess(success) { if (success) { notificationText.text = "Successfully saved settings."; } else { @@ -49,20 +49,20 @@ Rectangle { } } - function toggleWhitelist(enabled) { - Settings.setValue("private/whitelistEnabled", enabled); - console.info("Toggling Whitelist to:", enabled); + function toggleAllowlist(enabled) { + Settings.setValue("private/allowlistEnabled", enabled); + console.info("Toggling Allowlist to:", enabled); } function initCheckbox() { - var check = Settings.getValue("private/whitelistEnabled", false); + var check = Settings.getValue("private/allowlistEnabled", false); if (check) { - whitelistEnabled.toggle(); + allowlistEnabled.toggle(); } } - - + + anchors.fill: parent width: parent.width; height: 120; @@ -70,7 +70,7 @@ Rectangle { HifiStylesUit.RalewayRegular { id: titleText; - text: "Entity Script / QML Whitelist" + text: "Entity Script / QML Allowlist" // Text size size: 24; // Style @@ -89,13 +89,13 @@ Rectangle { initCheckbox(); } - id: whitelistEnabled; + id: allowlistEnabled; anchors.right: parent.right; anchors.top: parent.top; anchors.topMargin: 10; onToggled: { - toggleWhitelist(whitelistEnabled.checked) + toggleAllowlist(allowlistEnabled.checked) } Label { @@ -115,7 +115,7 @@ Rectangle { width: parent.width; height: 250; anchors.top: titleText.bottom; - + ScrollView { id: textAreaScrollView anchors.fill: parent; @@ -126,8 +126,8 @@ Rectangle { clip: false; TextArea { - id: whitelistTextArea - text: getWhitelistAsText(); + id: allowlistTextArea + text: getAllowlistAsText(); onTextChanged: notificationText.text = ""; width: parent.width; height: parent.height; @@ -136,7 +136,7 @@ Rectangle { color: "white"; } } - + Button { id: saveChanges anchors.topMargin: 5; @@ -155,8 +155,8 @@ Rectangle { elide: Text.ElideRight } text: "Save Changes" - onClicked: setWhitelistAsText(whitelistTextArea) - + onClicked: setAllowlistAsText(allowlistTextArea) + HifiStylesUit.RalewayRegular { id: notificationText; text: "" @@ -170,15 +170,15 @@ Rectangle { anchors.rightMargin: 10; } } - + HifiStylesUit.RalewayRegular { id: descriptionText; - text: - "The whitelist checks scripts and QML as they are loaded.
+ text: + "The allowlist checks scripts and QML as they are loaded.
Therefore, if a script is cached or has no reason to load again,
- removing it from the whitelist will have no effect until
+ removing it from the allowlist will have no effect until
it is reloaded.
- Separate your whitelisted domains by line, not commas. e.g. + Separate your allowlisted domains by line, not commas. e.g.
https://google.com/
hifi://the-spot/
@@ -186,7 +186,7 @@ Rectangle { https://mydomain.here/
Ensure there are no spaces or whitespace.

- For QML files, you can only whitelist each file individually
+ For QML files, you can only allowlist each file individually
ending with '.qml'." // Text size size: 16; diff --git a/interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml b/interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml index de7304b6fb..2cd8d5cabf 100644 --- a/interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml +++ b/interface/resources/qml/hifi/dialogs/security/ScriptSecurity.qml @@ -5,7 +5,7 @@ // Created by dr Karol Suprynowicz on 2024/03/24. // Copyright 2024 Overte e.V. // -// Based on EntityScriptQMLWhitelist.qml +// Based on EntityScriptQMLAllowlist.qml // Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com // Copyright 2019 Kalila L. // @@ -27,15 +27,15 @@ import "../../../windows" Rectangle { id: parentBody; - function getWhitelistAsText() { - var whitelist = Settings.getValue("private/scriptPermissionGetAvatarURLSafeURLs"); - var arrayWhitelist = whitelist.replace(",", "\n"); - return arrayWhitelist; + function getAllowlistAsText() { + var allowlist = Settings.getValue("private/scriptPermissionGetAvatarURLSafeURLs"); + var arrayAllowlist = allowlist.replace(",", "\n"); + return arrayAllowlist; } - function setWhitelistAsText(whitelistText) { - Settings.setValue("private/scriptPermissionGetAvatarURLSafeURLs", whitelistText.text); - notificationText.text = "Whitelist saved."; + function setAllowlistAsText(allowlistText) { + Settings.setValue("private/scriptPermissionGetAvatarURLSafeURLs", allowlistText.text); + notificationText.text = "Allowlist saved."; } function setAvatarProtection(enabled) { @@ -65,7 +65,7 @@ Rectangle { height: 60; CheckBox { - id: whitelistEnabled; + id: allowlistEnabled; checked: Settings.getValue("private/scriptPermissionGetAvatarURLEnable", true); @@ -73,7 +73,7 @@ Rectangle { anchors.top: parent.top; anchors.topMargin: 10; onToggled: { - setAvatarProtection(whitelistEnabled.checked) + setAvatarProtection(allowlistEnabled.checked) } Label { @@ -104,8 +104,8 @@ Rectangle { clip: false; TextArea { - id: whitelistTextArea - text: getWhitelistAsText(); + id: allowlistTextArea + text: getAllowlistAsText(); onTextChanged: notificationText.text = ""; width: parent.width; height: parent.height; @@ -133,7 +133,7 @@ Rectangle { elide: Text.ElideRight } text: "Save Changes" - onClicked: setWhitelistAsText(whitelistTextArea) + onClicked: setAllowlistAsText(allowlistTextArea) HifiStylesUit.RalewayRegular { id: notificationText; diff --git a/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml index db4cb0f7a5..1eb08ee952 100644 --- a/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml +++ b/interface/resources/qml/hifi/simplifiedUI/helpApp/about/HelpAbout.qml @@ -211,7 +211,7 @@ Flickable { wrapMode: Text.Wrap Component.onCompleted: { - var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU())); + var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getPrimaryGPU())); var gpuModel = gpu.model; if (!gpuModel || gpuModel.length === 0) { gpuModel = "Unknown"; @@ -336,7 +336,7 @@ Flickable { textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n"; textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n"; - var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getMasterGPU())); + var gpu = JSON.parse(PlatformInfo.getGPU(PlatformInfo.getPrimaryGPU())); var gpuModel = gpu.model; if (!gpuModel || gpuModel.length === 0) { gpuModel = "Unknown"; diff --git a/interface/resources/shaders/errorShader.frag b/interface/resources/shaders/errorShader.frag new file mode 100644 index 0000000000..acfd23505e --- /dev/null +++ b/interface/resources/shaders/errorShader.frag @@ -0,0 +1,30 @@ +vec3 getErrorColor() { + vec3 positionWS = iWorldOrientation * (_positionMS.xyz * iWorldScale) + iWorldPosition; + float checkSize = 0.1; + vec3 edges = round(mod(positionWS, vec3(checkSize)) / checkSize); + float checkerboard = mod(edges.x + edges.y + edges.z, 2.0); + return mix(vec3(1, 0, 1), vec3(0.0), checkerboard); +} + +// version 1 +vec3 getProceduralColor() { + return getErrorColor(); +} + +// version 2 +float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { + diffuse = getErrorColor(); + return 1.0; +} + +// version 3 +float getProceduralFragment(inout ProceduralFragment data) { + data.emissive = getErrorColor(); + return 1.0; +} + +// version 4 +float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition data) { + data.emissive = getErrorColor(); + return 1.0; +} diff --git a/interface/resources/shaders/errorSkyboxShader.frag b/interface/resources/shaders/errorSkyboxShader.frag new file mode 100644 index 0000000000..1c9b333ae5 --- /dev/null +++ b/interface/resources/shaders/errorSkyboxShader.frag @@ -0,0 +1,7 @@ +vec3 getSkyboxColor() { + vec3 normal = normalize(_normal); + float checkSize = 0.1; + vec3 edges = round(mod(normal, vec3(checkSize)) / checkSize); + float checkerboard = mod(edges.x + edges.y + edges.z, 2.0); + return mix(vec3(1, 0, 1), vec3(0.0), checkerboard); +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6c09bf32e0..f630bea863 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3293,9 +3293,9 @@ void Application::initializeUi() { { auto defaultUrlValidator = OffscreenQmlSurface::getUrlValidator(); auto newValidator = [=](const QUrl& url) -> bool { - QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; + QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]"; QList safeURLS = { "" }; - safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); + safeURLS += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); // PULL SAFEURLS FROM INTERFACE.JSON Settings @@ -3332,7 +3332,7 @@ void Application::initializeUi() { QmlContextCallback platformInfoCallback = [](QQmlContext* context) { context->setContextProperty("PlatformInfo", new PlatformInfoScriptingInterface()); }; - OffscreenQmlSurface::addWhitelistContextHandler({ + OffscreenQmlSurface::addAllowlistContextHandler({ QUrl{ "hifi/tablet/TabletAddressDialog.qml" }, QUrl{ "hifi/Card.qml" }, QUrl{ "hifi/Pal.qml" }, @@ -3342,7 +3342,7 @@ void Application::initializeUi() { QmlContextCallback ttsCallback = [](QQmlContext* context) { context->setContextProperty("TextToSpeech", DependencyManager::get().data()); }; - OffscreenQmlSurface::addWhitelistContextHandler({ + OffscreenQmlSurface::addAllowlistContextHandler({ QUrl{ "hifi/tts/TTS.qml" } }, ttsCallback); qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7017f2a083..3a0aec7534 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -46,6 +46,7 @@ #include "avatar/AvatarManager.h" #include "avatar/AvatarPackager.h" #include "AvatarBookmarks.h" +#include #include "DomainAccountManager.h" #include "MainWindow.h" #include "render/DrawStatus.h" @@ -310,13 +311,13 @@ Menu::Menu() { } }); - // Settings > Entity Script / QML Whitelist - action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script / QML Whitelist"); + // Settings > Entity Script / QML Allowlist + action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script / QML Allowlist"); connect(action, &QAction::triggered, [] { auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); auto hmd = DependencyManager::get(); - tablet->pushOntoStack("hifi/dialogs/security/EntityScriptQMLWhitelist.qml"); + tablet->pushOntoStack("hifi/dialogs/security/EntityScriptQMLAllowlist.qml"); if (!hmd->getShouldShowTablet()) { hmd->toggleShouldShowTablet(); @@ -540,7 +541,7 @@ Menu::Menu() { action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); connect(action, &QAction::triggered, [action] { - ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); + Procedural::enableProceduralShaders = action->isChecked(); }); { @@ -549,6 +550,13 @@ Menu::Menu() { drawStatusConfig, SLOT(setShowFade(bool))); } + { + action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ExtraLinearTosRGBConversion, 0, OpenGLDisplayPlugin::getExtraLinearToSRGBConversion()); + connect(action, &QAction::triggered, [action] { + OpenGLDisplayPlugin::setExtraLinearToSRGBConversion(action->isChecked()); + }); + } + // Developer > Assets >>> // Menu item is not currently needed but code should be kept in case it proves useful again at some stage. //#define WANT_ASSET_MIGRATION diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e0cdfdf4fd..61b028269e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -189,7 +189,7 @@ namespace MenuOption { const QString RunningScripts = "Running Scripts..."; const QString RunTimingTests = "Run Timing Tests"; const QString ScriptedMotorControl = "Enable Scripted Motor Control"; - const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist"; + const QString EntityScriptQMLAllowlist = "Entity Script / QML Allowlist"; const QString ScriptSecurity = "Script Security"; const QString ShowTrackedObjects = "Show Tracked Objects"; const QString SelfieCamera = "Selfie"; @@ -237,7 +237,8 @@ namespace MenuOption { const QString ComputeBlendshapes = "Compute Blendshapes"; const QString HighlightTransitions = "Highlight Transitions"; const QString MaterialProceduralShaders = "Enable Procedural Materials"; -} + const QString ExtraLinearTosRGBConversion = "Extra Linear to sRGB Conversion"; + } #endif // hifi_Menu_h diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index fc67de219b..ddefc780ba 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -75,13 +75,13 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP // Ugly case that prevent us to run deferred everywhere... bool isDeferredCapable = platform::Profiler::isRenderMethodDeferredCapable(); - auto masterDisplay = platform::getDisplay(platform::getMasterDisplay()); + auto primaryDisplay = platform::getDisplay(platform::getPrimaryDisplay()); // eval recommended PPI and Scale float recommendedPpiScale = 1.0f; const float RECOMMENDED_PPI[] = { 200.0f, 200.0f, 120.f, 160.f, 250.f}; - if (!masterDisplay.empty() && masterDisplay.count(platform::keys::display::ppi)) { - float ppi = masterDisplay[platform::keys::display::ppi]; + if (!primaryDisplay.empty() && primaryDisplay.count(platform::keys::display::ppi)) { + float ppi = primaryDisplay[platform::keys::display::ppi]; // only scale if the actual ppi is higher than the recommended ppi if (ppi > RECOMMENDED_PPI[preset]) { // make sure the scale is no less than a quarter diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7e8c1afff3..819949f6a3 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -97,7 +97,7 @@ int main(int argc, const char* argv[]) { ); QCommandLineOption protocolVersionOption( "protocolVersion", - "Writes the protocol version base64 signature to a file?", + "Writes the protocol version base64 signature to a file", "path" ); QCommandLineOption noUpdaterOption( @@ -275,10 +275,18 @@ int main(int argc, const char* argv[]) { "abortAfterInit", "Debug option. Aborts after initialization, right before the program starts running the event loop." ); + QCommandLineOption getProtocolVersionHashOption( + "getProtocolVersionHash", + "Debug option. Returns the network protocol version MD5 hash." + ); + QCommandLineOption getProtocolVersionDataOption( + "getProtocolVersionData", + "Debug option. Returns the network protocol detailed data in JSON." + ); // "--qmljsdebugger", which appears in output from "--help-all". // Those below don't seem to be optional. - // --ignore-gpu-blacklist + // --ignore-gpu-blocklist // --suppress-settings-reset @@ -321,6 +329,8 @@ int main(int argc, const char* argv[]) { parser.addOption(abortAfterStartupOption); parser.addOption(abortAfterInitOption); parser.addOption(getPluginsOption); + parser.addOption(getProtocolVersionHashOption); + parser.addOption(getProtocolVersionDataOption); QString applicationPath; @@ -455,6 +465,34 @@ int main(int argc, const char* argv[]) { return 1; } } + if (parser.isSet(getProtocolVersionHashOption)) { + std::cout << protocolVersionsSignatureHex().toStdString() << std::endl; + return 0; + } + if (parser.isSet(getProtocolVersionDataOption)) { + auto protocolMap = protocolVersionsSignatureMap(); + QMetaEnum packetMetaEnum = QMetaEnum::fromType(); + + QJsonArray packetTypesList; + auto keyList = protocolMap.keys(); + std::sort(keyList.begin(), keyList.end()); // Sort by numeric value + + for(const auto packet : keyList) { + QJsonObject data; + int intValue = static_cast(packet); + QString keyName = packetMetaEnum.valueToKey(intValue); + + data["name"] = keyName; + data["value"] = intValue; + data["version"] = versionForPacketType(packet); + + packetTypesList.append(data); + } + + std::cout << QJsonDocument(packetTypesList).toJson().toStdString() << std::endl; + return 0; + } + static const QString APPLICATION_CONFIG_FILENAME = "config.json"; QDir applicationDir(applicationPath); diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index 842de9f48a..f652639d20 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -408,9 +408,9 @@ CollisionRegion CollisionPick::getMathematicalPick() const { void CollisionPick::filterIntersections(std::vector& intersections) const { const QVector& ignoreItems = getIgnoreItems(); const QVector& includeItems = getIncludeItems(); - bool isWhitelist = !includeItems.empty(); + bool isAllowlist = !includeItems.empty(); - if (!isWhitelist && ignoreItems.empty()) { + if (!isAllowlist && ignoreItems.empty()) { return; } @@ -420,7 +420,7 @@ void CollisionPick::filterIntersections(std::vector& intersec for (int i = 0; i < n; i++) { auto& intersection = intersections[i]; const QUuid& id = intersection.foundID; - if (!ignoreItems.contains(id) && (!isWhitelist || includeItems.contains(id))) { + if (!ignoreItems.contains(id) && (!isAllowlist || includeItems.contains(id))) { filteredIntersections.push_back(intersection); } } diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 8f44959d04..532e9ff73e 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -533,7 +533,7 @@ void Audio::setAvatarGain(float gain) { } withWriteLock([&] { - // ask the NodeList to set the master avatar gain + // ask the NodeList to set the primary avatar gain DependencyManager::get()->setAvatarGain(QUuid(), gain); }); diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.cpp b/interface/src/scripting/PlatformInfoScriptingInterface.cpp index b87175bb74..b68859d541 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.cpp +++ b/interface/src/scripting/PlatformInfoScriptingInterface.cpp @@ -182,8 +182,8 @@ bool PlatformInfoScriptingInterface::isStandalone() { int PlatformInfoScriptingInterface::getNumCPUs() { return platform::getNumCPUs(); } -int PlatformInfoScriptingInterface::getMasterCPU() { - return platform::getMasterCPU(); +int PlatformInfoScriptingInterface::getPrimaryCPU() { + return platform::getPrimaryCPU(); } QString PlatformInfoScriptingInterface::getCPU(int index) { auto desc = platform::getCPU(index); @@ -193,8 +193,8 @@ QString PlatformInfoScriptingInterface::getCPU(int index) { int PlatformInfoScriptingInterface::getNumGPUs() { return platform::getNumGPUs(); } -int PlatformInfoScriptingInterface::getMasterGPU() { - return platform::getMasterGPU(); +int PlatformInfoScriptingInterface::getPrimaryGPU() { + return platform::getPrimaryGPU(); } QString PlatformInfoScriptingInterface::getGPU(int index) { auto desc = platform::getGPU(index); @@ -204,8 +204,8 @@ QString PlatformInfoScriptingInterface::getGPU(int index) { int PlatformInfoScriptingInterface::getNumDisplays() { return platform::getNumDisplays(); } -int PlatformInfoScriptingInterface::getMasterDisplay() { - return platform::getMasterDisplay(); +int PlatformInfoScriptingInterface::getPrimaryDisplay() { + return platform::getPrimaryDisplay(); } QString PlatformInfoScriptingInterface::getDisplay(int index) { auto desc = platform::getDisplay(index); diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index c558eeeedc..c22593c927 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -106,8 +106,8 @@ public slots: * @function PlatformInfo.getGraphicsCardType * @returns {string} The model of the graphics card currently being used. * @deprecated This function is deprecated and will be removed. - * Use JSON.parse({@link PlatformInfo.getGPU|PlatformInfo.getGPU(} - * {@link PlatformInfo.getMasterGPU|PlatformInfo.getMasterGPU() )}).model + * Use JSON.parse({@link PlatformInfo.getGPU|PlatformInfo.getGPU(} + * {@link PlatformInfo.getPrimaryGPU|PlatformInfo.getPrimaryGPU() )}).model * instead. */ QString getGraphicsCardType(); @@ -149,11 +149,11 @@ public slots: int getNumCPUs(); /*@jsdoc - * Gets the index number of the master CPU. - * @function PlatformInfo.getMasterCPU - * @returns {number} The index of the master CPU. + * Gets the index number of the primary CPU. + * @function PlatformInfo.getPrimaryCPU + * @returns {number} The index of the primary CPU. */ - int getMasterCPU(); + int getPrimaryCPU(); /*@jsdoc * Gets the platform description of a CPU. @@ -178,11 +178,11 @@ public slots: int getNumGPUs(); /*@jsdoc - * Gets the index number of the master GPU. - * @function PlatformInfo.getMasterGPU - * @returns {number} The index of the master GPU. + * Gets the index number of the primary GPU. + * @function PlatformInfo.getPrimaryGPU + * @returns {number} The index of the primary GPU. */ - int getMasterGPU(); + int getPrimaryGPU(); /*@jsdoc * Gets the platform description of a GPU. @@ -207,11 +207,11 @@ public slots: int getNumDisplays(); /*@jsdoc - * Gets the index number of the master display. - * @function PlatformInfo.getMasterDisplay - * @returns {number} The index of the master display. + * Gets the index number of the primary display. + * @function PlatformInfo.getPrimaryDisplay + * @returns {number} The index of the primary display. */ - int getMasterDisplay(); + int getPrimaryDisplay(); /*@jsdoc * Gets the platform description of a display. diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 258ba6784b..2761b1c9f0 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -221,8 +221,8 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap Application::setupQmlSurface(quickView->rootContext(), true); - //add any whitelisted callbacks - OffscreenUi::applyWhiteList(sourceUrl, quickView->rootContext()); + //add any allowlisted callbacks + OffscreenUi::applyAllowList(sourceUrl, quickView->rootContext()); /*@jsdoc * Configures how a NATIVE window is displayed. diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 4253002114..64146015d2 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -538,7 +538,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const } } } else if (targetType == IKTarget::Type::HmdHead) { - // An HmdHead target slaves the orientation of the end-effector by distributing rotation + // An HmdHead target workers the orientation of the end-effector by distributing rotation // deltas up the hierarchy. Its target position is enforced later (by shifting the hips). deltaRotation = target.getRotation() * glm::inverse(tipOrientation); const float ANGLE_DISTRIBUTION_FACTOR = 0.45f; diff --git a/libraries/audio/src/PositionalAudioStream.h b/libraries/audio/src/PositionalAudioStream.h index 01a714aeb4..9bd02a56e7 100644 --- a/libraries/audio/src/PositionalAudioStream.h +++ b/libraries/audio/src/PositionalAudioStream.h @@ -71,11 +71,11 @@ public: using IgnoreBox = AABox; - // called from single AudioMixerSlave while processing packets for node + // called from single AudioMixerWorker while processing packets for node void enableIgnoreBox(); void disableIgnoreBox() { _isIgnoreBoxEnabled = false; } - // thread-safe, called from AudioMixerSlave(s) while preparing mixes + // thread-safe, called from AudioMixerWorker(s) while preparing mixes bool isIgnoreBoxEnabled() const { return _isIgnoreBoxEnabled; } const IgnoreBox& getIgnoreBox() const { return _ignoreBox; } diff --git a/libraries/audio/src/flump3dec.cpp b/libraries/audio/src/flump3dec.cpp index 935ddecabb..7349cda7e4 100644 --- a/libraries/audio/src/flump3dec.cpp +++ b/libraries/audio/src/flump3dec.cpp @@ -4417,9 +4417,9 @@ bs_new () bs = (Bit_stream_struc *) calloc(1, sizeof(Bit_stream_struc)); g_return_val_if_fail (bs != NULL, NULL); - bs->master.cur_bit = 8; - bs->master.size = 0; - bs->master.cur_used = 0; + bs->primary.cur_bit = 8; + bs->primary.size = 0; + bs->primary.cur_used = 0; bs->read.cur_bit = 8; bs->read.size = 0; bs->read.cur_used = 0; @@ -4443,11 +4443,11 @@ bs_set_data (Bit_stream_struc * bs, const guint8 * data, gsize size) g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (size != 0, FALSE); - bs->master.data = data; - bs->master.cur_byte = (guint8 *) data; - bs->master.size = size; - bs->master.bitpos = 0; - bs->master.cur_used = 0; + bs->primary.data = data; + bs->primary.cur_byte = (guint8 *) data; + bs->primary.size = size; + bs->primary.bitpos = 0; + bs->primary.cur_used = 0; bs_reset (bs); return TRUE; } @@ -4494,7 +4494,7 @@ bs_eat (Bit_stream_struc * bs, BSReader * read, guint32 Nbits) } } -/* Advance the master position by Nbits */ +/* Advance the primary position by Nbits */ void bs_consume (Bit_stream_struc * bs, guint32 Nbits) { @@ -4503,7 +4503,7 @@ bs_consume (Bit_stream_struc * bs, guint32 Nbits) GST_DEBUG ("%d Consumed %d bits to end at %" G_GUINT64_FORMAT, n++, Nbits, bs_pos (bs) + Nbits); #endif - bs_eat (bs, &bs->master, Nbits); + bs_eat (bs, &bs->primary, Nbits); } /* Advance the read position by Nbits */ diff --git a/libraries/audio/src/flump3dec.h b/libraries/audio/src/flump3dec.h index 721e092b0a..688831da17 100644 --- a/libraries/audio/src/flump3dec.h +++ b/libraries/audio/src/flump3dec.h @@ -197,10 +197,10 @@ typedef struct BSReader typedef struct Bit_stream_struc { - BSReader master; /* Master tracking position, advanced + BSReader primary; /* Primary tracking position, advanced * by bs_consume() */ BSReader read; /* Current read position, set back to the - * master by bs_reset() */ + * primary by bs_reset() */ } Bit_stream_struc; /* Create and initialise a new bitstream reader */ @@ -209,25 +209,25 @@ Bit_stream_struc *bs_new (); /* Release a bitstream reader */ void bs_free (Bit_stream_struc * bs); -/* Reset the current read position to the master position */ +/* Reset the current read position to the primary position */ static inline void bs_reset (Bit_stream_struc * bs) { - memcpy (&bs->read, &bs->master, sizeof (BSReader)); + memcpy (&bs->read, &bs->primary, sizeof (BSReader)); } -/* Reset master and read states */ +/* Reset primary and read states */ static inline void bs_flush (Bit_stream_struc * bs) { g_return_if_fail (bs != NULL); - bs->master.cur_bit = 8; - bs->master.size = 0; - bs->master.cur_used = 0; - bs->master.cur_byte = NULL; - bs->master.data = NULL; - bs->master.bitpos = 0; + bs->primary.cur_bit = 8; + bs->primary.size = 0; + bs->primary.cur_used = 0; + bs->primary.cur_byte = NULL; + bs->primary.data = NULL; + bs->primary.bitpos = 0; bs_reset (bs); } @@ -235,7 +235,7 @@ bs_flush (Bit_stream_struc * bs) /* Set data as the stream for processing */ gboolean bs_set_data (Bit_stream_struc * bs, const guint8 * data, gsize size); -/* Advance the master position by Nbits */ +/* Advance the primary position by Nbits */ void bs_consume (Bit_stream_struc * bs, guint32 Nbits); /* Number of bits available for reading */ @@ -253,14 +253,14 @@ void bs_skipbits (Bit_stream_struc * bs, guint32 N); /* give number of consumed bytes */ static inline gsize bs_get_consumed (Bit_stream_struc * bs) { - return bs->master.cur_used; + return bs->primary.cur_used; } /* Current bitstream position in bits */ static inline guint64 bs_pos (Bit_stream_struc * bs) { - return bs->master.bitpos; + return bs->primary.bitpos; } /* Current read bitstream position in bits */ diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d3bf8a3282..916e09668b 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1704,7 +1704,7 @@ protected: void unpackSkeletonModelURL(const QByteArray& data); void unpackSkeletonData(const QByteArray& data); - // isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "master" + // isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "primary" // Audio Mixer that the replicated avatar is connected to. bool _isReplicated{ false }; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 024d9a0ab6..97c73603e1 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -112,14 +112,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { return Parent::internalActivate(); } -gpu::PipelinePointer Basic2DWindowOpenGLDisplayPlugin::getRenderTexturePipeline() { -#if defined(Q_OS_ANDROID) - return _linearToSRGBPipeline; -#else - return _drawTexturePipeline; -#endif -} - void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { #if defined(Q_OS_ANDROID) auto& virtualPadManager = VirtualPad::Manager::instance(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 68301ff8b4..cc304c19c2 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -37,8 +37,6 @@ public: virtual void pluginUpdate() override {}; - virtual gpu::PipelinePointer getRenderTexturePipeline() override; - protected: mutable bool _isThrottled = false; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 03a463c82a..6ea10f6327 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,8 @@ using namespace shader::gpu::program; extern QThread* RENDER_THREAD; +Setting::Handle OpenGLDisplayPlugin::_extraLinearToSRGBConversionSetting("extraLinearToSRGBConversion", false); + class PresentThread : public QThread, public Dependency { using Mutex = std::mutex; using Condition = std::condition_variable; @@ -956,5 +959,16 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne } gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() { - return _drawTexturePipeline; +#ifdef USE_GLES + if (!_extraLinearToSRGBConversionSetting.isSet()) { + const gl::ContextInfo &contextInfo = gl::ContextInfo::get(); + _extraLinearToSRGBConversionSetting.set(std::find(contextInfo.extensions.cbegin(), contextInfo.extensions.cend(), "GL_EXT_framebuffer_sRGB") == contextInfo.extensions.cend()); + } +#endif + + if (getExtraLinearToSRGBConversion()) { + return _linearToSRGBPipeline; + } else { + return _drawTexturePipeline; + } } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 15cebf7e3a..0df0d9ac3e 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -86,6 +87,9 @@ public: QOpenGLFramebufferObject* target, GLsync* fenceSync) override; + static void setExtraLinearToSRGBConversion(bool value) { _extraLinearToSRGBConversionSetting.set(value); } + static bool getExtraLinearToSRGBConversion() { return _extraLinearToSRGBConversionSetting.get(); }; + protected: friend class PresentThread; @@ -201,4 +205,7 @@ protected: QImage getScreenshot(float aspectRatio); QImage getSecondaryCameraScreenshot(); + +private: + static Setting::Handle _extraLinearToSRGBConversionSetting; }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a28cf0b790..f252561501 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -65,8 +65,8 @@ EntityTree::~EntityTree() { //eraseAllOctreeElements(false); // KEEP THIS } -void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) { - _entityScriptSourceWhitelist = entityScriptSourceWhitelist.split(',', Qt::SkipEmptyParts); +void EntityTree::setEntityScriptSourceAllowlist(const QString& entityScriptSourceAllowlist) { + _entityScriptSourceAllowlist = entityScriptSourceAllowlist.split(',', Qt::SkipEmptyParts); } @@ -1411,17 +1411,17 @@ void EntityTree::bumpTimestamp(EntityItemProperties& properties) { //fixme put c properties.setLastEdited(properties.getLastEdited() + LAST_EDITED_SERVERSIDE_BUMP); } -bool EntityTree::isScriptInWhitelist(const QString& scriptProperty) { +bool EntityTree::isScriptInAllowlist(const QString& scriptProperty) { // grab a URL representation of the entity script so we can check the host for this script auto entityScriptURL = QUrl::fromUserInput(scriptProperty); - for (const auto& whiteListedPrefix : _entityScriptSourceWhitelist) { - auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix); + for (const auto& allowListedPrefix : _entityScriptSourceAllowlist) { + auto allowListURL = QUrl::fromUserInput(allowListedPrefix); - // check if this script URL matches the whitelist domain and, optionally, is beneath the path - if (entityScriptURL.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 && - entityScriptURL.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) { + // check if this script URL matches the allowlist domain and, optionally, is beneath the path + if (entityScriptURL.host().compare(allowListURL.host(), Qt::CaseInsensitive) == 0 && + entityScriptURL.path().startsWith(allowListURL.path(), Qt::CaseInsensitive)) { return true; } } @@ -1504,18 +1504,18 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } } - if (validEditPacket && !_entityScriptSourceWhitelist.isEmpty()) { + if (validEditPacket && !_entityScriptSourceAllowlist.isEmpty()) { bool wasDeletedBecauseOfClientScript = false; - // check the client entity script to make sure its URL is in the whitelist + // check the client entity script to make sure its URL is in the allowlist if (!properties.getScript().isEmpty()) { - bool clientScriptPassedWhitelist = isScriptInWhitelist(properties.getScript()); + bool clientScriptPassedAllowlist = isScriptInAllowlist(properties.getScript()); - if (!clientScriptPassedWhitelist) { + if (!clientScriptPassedAllowlist) { if (wantEditLogging()) { qCDebug(entities) << "User [" << senderNode->getUUID() - << "] attempting to set entity script not on whitelist, edit rejected"; + << "] attempting to set entity script not on allowlist, edit rejected"; } // If this was an add, we also want to tell the client that sent this edit that the entity was not added. @@ -1530,20 +1530,20 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } } - // check all server entity scripts to make sure their URLs are in the whitelist + // check all server entity scripts to make sure their URLs are in the allowlist if (!properties.getServerScripts().isEmpty()) { - bool serverScriptPassedWhitelist = isScriptInWhitelist(properties.getServerScripts()); + bool serverScriptPassedAllowlist = isScriptInAllowlist(properties.getServerScripts()); - if (!serverScriptPassedWhitelist) { + if (!serverScriptPassedAllowlist) { if (wantEditLogging()) { qCDebug(entities) << "User [" << senderNode->getUUID() - << "] attempting to set server entity script not on whitelist, edit rejected"; + << "] attempting to set server entity script not on allowlist, edit rejected"; } // If this was an add, we also want to tell the client that sent this edit that the entity was not added. if (isAdd) { // Make sure we didn't already need to send back a delete because the client script failed - // the whitelist check + // the allowlist check if (!wasDeletedBecauseOfClientScript) { QWriteLocker locker(&_recentlyDeletedEntitiesLock); _recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c93a3b1527..ec209b37ad 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -63,7 +63,7 @@ public: void setEntityMaxTmpLifetime(float maxTmpEntityLifetime) { _maxTmpEntityLifetime = maxTmpEntityLifetime; } - void setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist); + void setEntityScriptSourceAllowlist(const QString& entityScriptSourceAllowlist); /// Implements our type specific root element factory virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL) override; @@ -300,7 +300,7 @@ protected: void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode); - bool isScriptInWhitelist(const QString& scriptURL); + bool isScriptInAllowlist(const QString& scriptURL); QReadWriteLock _newlyCreatedHooksLock; QVector _newlyCreatedHooks; @@ -363,7 +363,7 @@ protected: bool filterProperties(const EntityItemPointer& existingEntity, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, FilterType filterType) const; bool _hasEntityEditFilter{ false }; - QStringList _entityScriptSourceWhitelist; + QStringList _entityScriptSourceAllowlist; MovingEntitiesOperator _entityMover; QHash _entitiesToAdd; diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 9220f301d6..4050e1ee2b 100644 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -126,7 +126,7 @@ protected: const Shaders _shaders; - // The type of the shader, the master key + // The type of the shader, the primary key const Type _type; // Number of attempts to compile the shader diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index a0cfc60b6e..907f9ff392 100644 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -405,7 +405,7 @@ public: Stamp getDataStamp() const { return _storage->getStamp(); } // The theoretical size in bytes of data stored in the texture - // For the master (level) first level of mip + // For the primary (level) first level of mip Size getSize() const override { return _size; } // Size and format diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index 083a1146be..425b8deed8 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -465,7 +465,7 @@ float fetchUVAnimationMaskMap(vec2 uv) { <@func evalMaterialShadingShift(fetchedShadingShift, materialShadingShift, matKey, shadingShift)@> { <$shadingShift$> = mix(0.0, <$materialShadingShift$>, float((<$matKey$> & SHADING_SHIFT_VAL_BIT) != 0)); - <$shadingShift$> += mix(0.0, <$fetchedShadingShift$>.r, float((<$matKey$> & SHADING_SHIFT_MAP_BIT) != 0)); + <$shadingShift$> += mix(0.0, <$fetchedShadingShift$>, float((<$matKey$> & SHADING_SHIFT_MAP_BIT) != 0)); } <@endfunc@> diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 3ae0277e13..9454853418 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -4,7 +4,7 @@ // // Created by Stephen Birarda on 2/18/2014. // Copyright 2014 High Fidelity, Inc. -// Copyright 2023 Overte e.V. +// Copyright 2023-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -696,7 +696,8 @@ void AccountManager::setAccessTokens(const QString& response) { if (!rootObject.contains("access_token") || !rootObject.contains("expires_in") || !rootObject.contains("token_type")) { // TODO: error handling - malformed token response - qCDebug(networking) << "Received a response for password grant that is missing one or more expected values."; + qCWarning(networking) << "Error setting access token. Received a response for password grant that is missing one or more expected values."; + qCWarning(networking) << "Response:" << QJsonDocument(rootObject).toJson(QJsonDocument::Compact); } else { // clear the path from the response URL so we have the right root URL for this access token QUrl rootURL = rootObject.contains("url") ? rootObject["url"].toString() : _authURL; @@ -714,7 +715,7 @@ void AccountManager::setAccessTokens(const QString& response) { } } else { // TODO: error handling - qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString(); + qCWarning(networking) << "Error in response for password grant -" << rootObject["error"].toString(); emit loginFailed(); } } @@ -731,7 +732,8 @@ void AccountManager::requestAccessTokenFinished() { if (!rootObject.contains("access_token") || !rootObject.contains("expires_in") || !rootObject.contains("token_type")) { // TODO: error handling - malformed token response - qCDebug(networking) << "Received a response for password grant that is missing one or more expected values."; + qCWarning(networking) << "Error requesting access token. Received a response for password grant that is missing one or more expected values."; + qCWarning(networking) << "Response:" << QJsonDocument(rootObject).toJson(QJsonDocument::Compact); } else { // clear the path from the response URL so we have the right root URL for this access token QUrl rootURL = requestReply->url(); @@ -750,7 +752,7 @@ void AccountManager::requestAccessTokenFinished() { } } else { // TODO: error handling - qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString(); + qCWarning(networking) << "Error in response for password grant -" << rootObject["error"].toString(); emit loginFailed(); } } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index a230970909..3918375f5b 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -1250,7 +1250,7 @@ void NodeList::setAvatarGain(const QUuid& nodeID, float gain) { setAvatarGainPacket->writePrimitive(packFloatGainToByte(fastExp2f(gain / 6.02059991f))); if (nodeID.isNull()) { - qCDebug(networking) << "Sending Set MASTER Avatar Gain packet with Gain:" << gain; + qCDebug(networking) << "Sending Set PRIMARY Avatar Gain packet with Gain:" << gain; sendPacket(std::move(setAvatarGainPacket), *audioMixer); diff --git a/libraries/networking/src/UserActivityLogger.cpp b/libraries/networking/src/UserActivityLogger.cpp index d506e0c549..11f2021274 100644 --- a/libraries/networking/src/UserActivityLogger.cpp +++ b/libraries/networking/src/UserActivityLogger.cpp @@ -137,7 +137,7 @@ void UserActivityLogger::changedDomain(QString domainURL) { } void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceName) { - static QStringList DEVICE_BLACKLIST = { + static QStringList DEVICE_BLOCKLIST = { "Desktop", "NullDisplayPlugin", "3D TV - Side by Side Stereo", @@ -145,7 +145,7 @@ void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceNam "Keyboard/Mouse" }; - if (DEVICE_BLACKLIST.contains(deviceName) || deviceName.isEmpty()) { + if (DEVICE_BLOCKLIST.contains(deviceName) || deviceName.isEmpty()) { return; } diff --git a/libraries/networking/src/crash-handler/CrashHandlerBackend_Crashpad.cpp b/libraries/networking/src/crash-handler/CrashHandlerBackend_Crashpad.cpp index 1b93ebecb4..70b0189f29 100644 --- a/libraries/networking/src/crash-handler/CrashHandlerBackend_Crashpad.cpp +++ b/libraries/networking/src/crash-handler/CrashHandlerBackend_Crashpad.cpp @@ -457,6 +457,11 @@ bool startCrashHandler(std::string appPath, std::string crashURL, std::string cr } void setCrashReportingEnabled(bool enabled) { + if (!crashpadDatabase) { + qCCritical(crash_handler) << "Can't set to enabled, crash handler not initialized!"; + return; + } + auto settings = crashpadDatabase->GetSettings(); settings->SetUploadsEnabled(enabled); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index e561bfe21e..2aafc5501e 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -130,6 +130,10 @@ void sendWrongProtocolVersionsSignature(bool sendWrongVersion) { static QByteArray protocolVersionSignature; static QString protocolVersionSignatureBase64; +static QString protocolVersionSignatureHex; +static QMap protocolVersionMap; + + static void ensureProtocolVersionsSignature() { static std::once_flag once; std::call_once(once, [&] { @@ -139,12 +143,14 @@ static void ensureProtocolVersionsSignature() { stream << numberOfProtocols; for (uint8_t packetType = 0; packetType < numberOfProtocols; packetType++) { uint8_t packetTypeVersion = static_cast(versionForPacketType(static_cast(packetType))); + protocolVersionMap[static_cast(packetType)] = packetTypeVersion; stream << packetTypeVersion; } QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(buffer); protocolVersionSignature = hash.result(); protocolVersionSignatureBase64 = protocolVersionSignature.toBase64(); + protocolVersionSignatureHex = protocolVersionSignature.toHex(0); }); } QByteArray protocolVersionsSignature() { @@ -161,3 +167,13 @@ QString protocolVersionsSignatureBase64() { ensureProtocolVersionsSignature(); return protocolVersionSignatureBase64; } + +QString protocolVersionsSignatureHex() { + ensureProtocolVersionsSignature(); + return protocolVersionSignatureHex; +} + +QMap protocolVersionsSignatureMap() { + ensureProtocolVersionsSignature(); + return protocolVersionMap; +} \ No newline at end of file diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 3badfdf418..bc36d9444a 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -31,8 +31,15 @@ class PacketTypeEnum { Q_GADGET Q_ENUMS(Value) public: - // If adding a new packet packetType, you can replace one marked usable or add at the end. - // This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t + + /** + * @brief Packet type identifier + * + * Identifies the type of packet being sent. + * + * @note If adding a new packet packetType, you can replace one marked usable or add at the end. + * @note This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t + */ enum class Value : uint8_t { Unknown, DomainConnectRequestPending, @@ -143,6 +150,8 @@ public: NUM_PACKET_TYPE }; + Q_ENUM(Value) + const static QHash getReplicatedPacketMapping() { const static QHash REPLICATED_PACKET_MAPPING { { PacketTypeEnum::Value::MicrophoneAudioNoEcho, PacketTypeEnum::Value::ReplicatedMicrophoneAudioNoEcho }, @@ -219,10 +228,60 @@ const int NUM_BYTES_MD5_HASH = 16; // NOTE: There is a max limit of 255, hopefully we have a better way to manage this by then. typedef uint8_t PacketVersion; +/** + * @brief Returns the version number of the given packet type + * + * If the implementation of a packet type is modified in an incompatible way, the implementation + * of this function needs to be modified to return an incremented value. + * + * This is used to determine whether the protocol is compatible between client and server. + * + * @note Version is limited to a max of 255. + * + * @param packetType Type of packet + * @return PacketVersion Version + */ PacketVersion versionForPacketType(PacketType packetType); -QByteArray protocolVersionsSignature(); /// returns a unique signature for all the current protocols + +/** + * @brief Returns a unique signature for all the current protocols + * + * This computes a MD5 hash that expresses the state of the protocol's specification. The calculation + * is done in ensureProtocolVersionsSignature and accounts for the following: + * + * * Number of known packet types + * * versionForPacketType(type) for each packet type. + * + * There's no provision for backwards compatibility, anything that changes this calculation is a protocol break. + * + * @return QByteArray MD5 digest as a byte array + */ +QByteArray protocolVersionsSignature(); + +/*** + * @brief Returns a unique signature for all the current protocols + * + * Same as protocolVersionsSignature(), in base64. + */ QString protocolVersionsSignatureBase64(); +/*** + * @brief Returns a unique signature for all the current protocols + * + * Same as protocolVersionsSignature(), in hex; + */ +QString protocolVersionsSignatureHex(); + +/*** + * @brief Returns the data used to compute the protocol version + * + * The key is the packet type. The value is the version for that packet type. + * + * Used for aiding in development. + */ +QMap protocolVersionsSignatureMap(); + + #if (PR_BUILD || DEV_BUILD) void sendWrongProtocolVersionsSignature(bool sendWrongVersion); /// for debugging version negotiation #endif @@ -428,4 +487,5 @@ enum class AvatarQueryVersion : PacketVersion { ConicalFrustums = 22 }; + #endif // hifi_PacketHeaders_h diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index ac36d37aaa..bbb852c0be 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -655,7 +655,7 @@ uint8_t EntityMotionState::getSimulationPriority() const { return _entity->getSimulationPriority(); } -void EntityMotionState::slaveBidPriority() { +void EntityMotionState::workerBidPriority() { _bumpedPriority = glm::max(_bumpedPriority, _entity->getSimulationPriority()); } diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index be6f5c0658..eea53b4d30 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -111,7 +111,7 @@ protected: void updateServerPhysicsVariables(); bool remoteSimulationOutOfSync(uint32_t simulationStep); - void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity + void workerBidPriority(); // computeNewBidPriority() with value stored in _entity void clearObjectVelocities() const; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index d0d900e14d..27e0a463cf 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -602,7 +602,7 @@ void PhysicalEntitySimulation::sendOwnershipBids(uint32_t numSubsteps) { // in the EntityMotionState::_serverFoo variables (please see comments in EntityMotionState.h) // therefore we need to immediately send an update so that the values stored are what we're // "telling" the server rather than what we've been "hearing" from the server. - _bids[i]->slaveBidPriority(); + _bids[i]->workerBidPriority(); _bids[i]->sendUpdate(_entityPacketSender, numSubsteps); addOwnership(_bids[i]); diff --git a/libraries/platform/src/platform/Platform.h b/libraries/platform/src/platform/Platform.h index 8cda6332ee..1d5d625de1 100644 --- a/libraries/platform/src/platform/Platform.h +++ b/libraries/platform/src/platform/Platform.h @@ -21,15 +21,15 @@ bool enumeratePlatform(); int getNumCPUs(); json getCPU(int index); -int getMasterCPU(); +int getPrimaryCPU(); int getNumGPUs(); json getGPU(int index); -int getMasterGPU(); +int getPrimaryGPU(); int getNumDisplays(); json getDisplay(int index); -int getMasterDisplay(); +int getPrimaryDisplay(); json getMemory(); diff --git a/libraries/platform/src/platform/PlatformKeys.h b/libraries/platform/src/platform/PlatformKeys.h index 9bd9d47890..63cab3c7f7 100644 --- a/libraries/platform/src/platform/PlatformKeys.h +++ b/libraries/platform/src/platform/PlatformKeys.h @@ -20,7 +20,7 @@ namespace platform { namespace keys{ extern const char* model; extern const char* clockSpeed; extern const char* numCores; - extern const char* isMaster; + extern const char* isPrimary; } namespace gpu { extern const char* vendor; @@ -32,7 +32,7 @@ namespace platform { namespace keys{ extern const char* videoMemory; extern const char* driver; extern const char* displays; - extern const char* isMaster; + extern const char* isPrimary; } namespace graphicsAPI { extern const char* name; @@ -90,7 +90,7 @@ namespace platform { namespace keys{ extern const char* modeRefreshrate; extern const char* modeWidth; extern const char* modeHeight; - extern const char* isMaster; + extern const char* isPrimary; } namespace memory { extern const char* memTotal; diff --git a/libraries/platform/src/platform/Profiler.cpp b/libraries/platform/src/platform/Profiler.cpp index f64cc66059..a9c4a2318c 100644 --- a/libraries/platform/src/platform/Profiler.cpp +++ b/libraries/platform/src/platform/Profiler.cpp @@ -32,9 +32,9 @@ Profiler::Tier Profiler::profilePlatform() { return platformTier; } - // Not filtered yet, let s try to make sense of the master cpu and master gpu info - auto cpuInfo = platform::getCPU(platform::getMasterCPU()); - auto gpuInfo = platform::getGPU(platform::getMasterGPU()); + // Not filtered yet, let's try to make sense of the primary cpu and primary gpu info + auto cpuInfo = platform::getCPU(platform::getPrimaryCPU()); + auto gpuInfo = platform::getGPU(platform::getPrimaryGPU()); if (filterOnProcessors(computerInfo, cpuInfo, gpuInfo, platformTier)) { return platformTier; } @@ -62,7 +62,7 @@ bool filterOnComputerMACOS(const platform::json& computer, Profiler::Tier& tier) // The simple rule for mac is // if it s an intel gpu then LOW // else go mid - auto gpu = platform::getGPU(platform::getMasterGPU()); + auto gpu = platform::getGPU(platform::getPrimaryGPU()); if (gpu.count(keys::gpu::vendor)) { std::string gpuVendor = gpu[keys::gpu::vendor].get(); diff --git a/libraries/platform/src/platform/backend/MACOSPlatform.cpp b/libraries/platform/src/platform/backend/MACOSPlatform.cpp index 5a7b40f71b..1308b8a972 100644 --- a/libraries/platform/src/platform/backend/MACOSPlatform.cpp +++ b/libraries/platform/src/platform/backend/MACOSPlatform.cpp @@ -67,7 +67,7 @@ void MACOSInstance::enumerateGpusAndDisplays() { auto displaySizeHeightInches = displaySize.height * MM_TO_IN; auto displayBounds = CGDisplayBounds(displayID); - auto displayMaster =CGDisplayIsMain(displayID); + auto displayPrimary =CGDisplayIsMain(displayID); auto displayUnit =CGDisplayUnitNumber(displayID); auto displayModel =CGDisplayModelNumber(displayID); @@ -112,8 +112,8 @@ void MACOSInstance::enumerateGpusAndDisplays() { // refreshrate display[keys::display::modeRefreshrate] = displayRefreshrate; - // Master display ? - display[keys::display::isMaster] = (displayMaster ? true : false); + // Primary display ? + display[keys::display::isPrimary] = (displayPrimary ? true : false); // Macos specific display["macos_unit"] = displayUnit; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 5c128ba28f..3b1e3e1db7 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -30,7 +30,7 @@ namespace platform { namespace keys { * @property {string} vendor - The CPU vendor (e.g., "Intel" or "AMD"). * @property {string} model - The CPU model. * @property {number} numCores - The number of logical cores. - * @property {boolean} isMaster - true if the CPU is the "master" or primary CPU, false or + * @property {boolean} isPrimary - true if the CPU is the primary CPU, false or * undefined if it isn't. */ namespace cpu { @@ -41,7 +41,7 @@ namespace platform { namespace keys { const char* model = "model"; const char* clockSpeed = "clockSpeed"; // FIXME: Not used. const char* numCores = "numCores"; - const char* isMaster = "isMaster"; + const char* isPrimary = "isPrimary"; } /*@jsdoc @@ -53,7 +53,7 @@ namespace platform { namespace keys { * @property {number} videoMemory - The size of the GPU's video memory, in MB. * @property {number[]} displays - The index numbers of the displays currently being driven by the GPU. An empty array if * the GPU is currently not driving any displays. - * @property {boolean} isMaster - true if the GPU is the "master" or primary GPU, false or + * @property {boolean} isPrimary - true if the GPU is the primary GPU, false or * undefined if it isn't. */ namespace gpu { @@ -66,7 +66,7 @@ namespace platform { namespace keys { const char* videoMemory = "videoMemory"; const char* driver = "driver"; const char* displays = "displays"; - const char* isMaster = "isMaster"; + const char* isPrimary = "isPrimary"; } /*@jsdoc @@ -175,7 +175,7 @@ namespace platform { namespace keys { * @property {number} modeRefreshrate - The refresh rate of the current display mode, in Hz. * @property {number} modeWidth - The width of the current display mode, in pixels. * @property {number} modeHeight - The height of the current display mode, in pixels. - * @property {boolean} isMaster - true if the GPU is the "master" or primary display, false or + * @property {boolean} isPrimary - true if the GPU is the primary display, false or * undefined if it isn't. */ namespace display { @@ -193,7 +193,7 @@ namespace platform { namespace keys { const char* modeRefreshrate = "modeRefreshrate"; const char* modeWidth = "modeWidth"; const char* modeHeight = "modeHeight"; - const char* isMaster = "isMaster"; + const char* isPrimary = "isPrimary"; } /*@jsdoc @@ -300,8 +300,8 @@ json platform::getCPU(int index) { return _instance->getCPU(index); } -int platform::getMasterCPU() { - return _instance->getMasterCPU(); +int platform::getPrimaryCPU() { + return _instance->getPrimaryCPU(); } int platform::getNumGPUs() { @@ -312,8 +312,8 @@ json platform::getGPU(int index) { return _instance->getGPU(index); } -int platform::getMasterGPU() { - return _instance->getMasterGPU(); +int platform::getPrimaryGPU() { + return _instance->getPrimaryGPU(); } int platform::getNumDisplays() { @@ -324,8 +324,8 @@ json platform::getDisplay(int index) { return _instance->getDisplay(index); } -int platform::getMasterDisplay() { - return _instance->getMasterDisplay(); +int platform::getPrimaryDisplay() { + return _instance->getPrimaryDisplay(); } json platform::getMemory() { diff --git a/libraries/platform/src/platform/backend/PlatformInstance.cpp b/libraries/platform/src/platform/backend/PlatformInstance.cpp index 114a53d2cc..5d86334054 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.cpp +++ b/libraries/platform/src/platform/backend/PlatformInstance.cpp @@ -41,8 +41,8 @@ bool Instance::enumeratePlatform() { enumerateNics(); enumerateGraphicsApis(); - // eval the master index for each platform scopes - updateMasterIndices(); + // eval the primary index for each platform scopes + updatePrimaryIndices(); // And profile the platform and put the tier in "computer" _computer[keys::computer::profileTier] = Profiler::TierNames[Profiler::profilePlatform()]; @@ -50,54 +50,54 @@ bool Instance::enumeratePlatform() { return true; } -void Instance::updateMasterIndices() { +void Instance::updatePrimaryIndices() { // We assume a single CPU at the moment: { if (!_cpus.empty()) { - _masterCPU = 0; - _cpus[0][keys::cpu::isMaster] = true; + _primaryCPU = 0; + _cpus[0][keys::cpu::isPrimary] = true; } else { - _masterCPU = NOT_FOUND; + _primaryCPU = NOT_FOUND; } } // Go through the displays list { - _masterDisplay = NOT_FOUND; + _primaryDisplay = NOT_FOUND; for (int i = 0; i < (int) _displays.size(); ++i) { const auto& display = _displays[i]; - if (display.count(keys::display::isMaster)) { - if (display[keys::display::isMaster].get()) { - _masterDisplay = i; + if (display.count(keys::display::isPrimary)) { + if (display[keys::display::isPrimary].get()) { + _primaryDisplay = i; break; } } } - // NO master display found, return the first one or NOT_FOUND if no display - if (_masterDisplay == NOT_FOUND) { + // NO primary display found, return the first one or NOT_FOUND if no display + if (_primaryDisplay == NOT_FOUND) { if (!_displays.empty()) { - _masterDisplay = 0; - _displays[0][keys::display::isMaster] = true; + _primaryDisplay = 0; + _displays[0][keys::display::isPrimary] = true; } } } - // From the master display decide the master gpu + // From the primary display decide the primary gpu { - _masterGPU = NOT_FOUND; - if (_masterDisplay != NOT_FOUND) { - const auto& display = _displays[_masterDisplay]; - // FInd the GPU index of the master display + _primaryGPU = NOT_FOUND; + if (_primaryDisplay != NOT_FOUND) { + const auto& display = _displays[_primaryDisplay]; + // FInd the GPU index of the primary display if (display.count(keys::display::gpu)) { - _masterGPU = display[keys::display::gpu]; - _gpus[_masterGPU][keys::gpu::isMaster] = true; + _primaryGPU = display[keys::display::gpu]; + _gpus[_primaryGPU][keys::gpu::isPrimary] = true; } } - // NO master GPU found from master display, bummer, return the first one or NOT_FOUND if no display - if (_masterGPU == NOT_FOUND) { + // NO primary GPU found from primary display, bummer, return the first one or NOT_FOUND if no display + if (_primaryGPU == NOT_FOUND) { if (!_gpus.empty()) { - _masterGPU = 0; - _gpus[0][keys::gpu::isMaster] = true; + _primaryGPU = 0; + _gpus[0][keys::gpu::isPrimary] = true; } } } diff --git a/libraries/platform/src/platform/backend/PlatformInstance.h b/libraries/platform/src/platform/backend/PlatformInstance.h index 2b263c21ef..93a57794bb 100644 --- a/libraries/platform/src/platform/backend/PlatformInstance.h +++ b/libraries/platform/src/platform/backend/PlatformInstance.h @@ -23,15 +23,15 @@ public: int getNumCPUs() { return (int)_cpus.size(); } json getCPU(int index); - int getMasterCPU() const { return _masterCPU; } + int getPrimaryCPU() const { return _primaryCPU; } int getNumGPUs() { return (int)_gpus.size(); } json getGPU(int index); - int getMasterGPU() const { return _masterGPU; } + int getPrimaryGPU() const { return _primaryGPU; } int getNumDisplays() { return (int)_displays.size(); } json getDisplay(int index); - int getMasterDisplay() const { return _masterDisplay; } + int getPrimaryDisplay() const { return _primaryDisplay; } json getMemory() { return _memory; } @@ -62,12 +62,12 @@ protected: json _memory; json _computer; - int _masterCPU{ -1 }; - int _masterGPU{ -1 }; - int _masterDisplay{ -1 }; + int _primaryCPU{ -1 }; + int _primaryGPU{ -1 }; + int _primaryDisplay{ -1 }; - // Traverse the cpus, gpus and displays to update the "master" index in each domain - void updateMasterIndices(); + // Traverse the cpus, gpus and displays to update the "primary" index in each domain + void updatePrimaryIndices(); }; diff --git a/libraries/platform/src/platform/backend/WINPlatform.cpp b/libraries/platform/src/platform/backend/WINPlatform.cpp index 2958374451..52d94ce157 100644 --- a/libraries/platform/src/platform/backend/WINPlatform.cpp +++ b/libraries/platform/src/platform/backend/WINPlatform.cpp @@ -167,8 +167,8 @@ void WINInstance::enumerateGpusAndDisplays() { // refreshrate display[keys::display::modeRefreshrate] = devMode.dmDisplayFrequency;; - // Master display ? - display[keys::display::isMaster] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY); + // Primary display ? + display[keys::display::isPrimary] = (bool) (monitorInfo.dwFlags & MONITORINFOF_PRIMARY); // Add the display index to the list of displays of the gpu displayIndices.push_back((int) _displays.size()); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 66dde1ca56..49d05d8059 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -28,6 +28,8 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural") +bool Procedural::enableProceduralShaders = false; + // User-data parsing constants static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity"; static const QString VERTEX_URL_KEY = "vertexShaderURL"; @@ -377,6 +379,27 @@ void Procedural::prepare(gpu::Batch& batch, _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); + // Error fallback: pink checkerboard + if (_errorFallbackFragmentSource.isEmpty()) { + QFile file(_errorFallbackFragmentPath); + file.open(QIODevice::ReadOnly); + _errorFallbackFragmentSource = QTextStream(&file).readAll(); + } + vertexSource.replacements.erase(PROCEDURAL_BLOCK); + fragmentSource.replacements[PROCEDURAL_BLOCK] = _errorFallbackFragmentSource.toStdString(); + gpu::ShaderPointer errorVertexShader = gpu::Shader::createVertex(vertexSource); + gpu::ShaderPointer errorFragmentShader = gpu::Shader::createPixel(fragmentSource); + gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(errorVertexShader, errorFragmentShader); + _errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState); + + // Disabled fallback: nothing + vertexSource.replacements.erase(PROCEDURAL_BLOCK); + fragmentSource.replacements.erase(PROCEDURAL_BLOCK); + gpu::ShaderPointer disabledVertexShader = gpu::Shader::createVertex(vertexSource); + gpu::ShaderPointer disabledFragmentShader = gpu::Shader::createPixel(fragmentSource); + gpu::ShaderPointer disabledProgram = gpu::Shader::createProgram(disabledVertexShader, disabledFragmentShader); + _disabledPipelines[key] = gpu::Pipeline::create(disabledProgram, _opaqueState); + _lastCompile = usecTimestampNow(); if (_firstCompile == 0) { _firstCompile = _lastCompile; @@ -385,8 +408,15 @@ void Procedural::prepare(gpu::Batch& batch, recompiledShader = true; } + gpu::PipelinePointer finalPipeline = recompiledShader ? _proceduralPipelines[key] : pipeline->second; + if (!enableProceduralShaders) { + finalPipeline = _disabledPipelines[key]; + } else if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) { + finalPipeline = _errorPipelines[key]; + } + // FIXME: need to handle forward rendering - batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second); + batch.setPipeline(finalPipeline); bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key; if (recreateUniforms) { @@ -533,4 +563,6 @@ void graphics::ProceduralMaterial::initializeProcedural() { // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural); _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent); + + _procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorShader.frag").path(); } \ No newline at end of file diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 39c619c687..9e6f102e36 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -124,12 +124,16 @@ public: gpu::Shader::Source _opaqueFragmentSource; gpu::Shader::Source _transparentFragmentSource; + QString _errorFallbackFragmentPath; + gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; static std::function opaqueStencil; static std::function transparentStencil; + static bool enableProceduralShaders; + protected: // DO NOT TOUCH // We have to pack these in a particular way to match the ProceduralCommon.slh @@ -176,11 +180,15 @@ protected: bool _shaderDirty { true }; bool _uniformsDirty { true }; + QString _errorFallbackFragmentSource; + // Rendering objects UniformLambdas _uniforms; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; std::unordered_map _proceduralPipelines; + std::unordered_map _errorPipelines; + std::unordered_map _disabledPipelines; StandardInputs _standardInputs; gpu::BufferPointer _standardInputsBuffer; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 432e02fe10..5cbf11f298 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -22,6 +22,8 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _crea _procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox); _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); + _procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorSkyboxShader.frag").path(); + _procedural.setDoesFade(false); // Adjust the pipeline state for background using the stencil test diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e095d9b15d..a77dc6b160 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -25,8 +25,6 @@ using namespace render; -bool ModelMeshPartPayload::enableMaterialProceduralShaders = false; - ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const uint64_t& created) : _meshIndex(meshIndex), @@ -345,9 +343,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) { } if (_shapeKey.hasOwnPipeline()) { - if (!(enableMaterialProceduralShaders)) { - return; - } auto procedural = std::static_pointer_cast(_drawMaterials.top().material); auto& schema = _drawMaterials.getSchemaBuffer().get(); glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b502865f94..0818340981 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -68,8 +68,6 @@ public: void setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes); - static bool enableMaterialProceduralShaders; - private: void initCache(const ModelPointer& model, int shapeID); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index f09a646ce6..58707bf4db 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -183,7 +183,7 @@ void Transaction::clear() { Scene::Scene(glm::vec3 origin, float size) : - _masterSpatialTree(origin, size) + _primarySpatialTree(origin, size) { _items.push_back(Item()); // add the itemID #0 to nothing } @@ -306,10 +306,10 @@ void Scene::resetItems(const Transaction::Resets& transactions) { // Update the item's container assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey); + auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey); item.resetCell(newCell, newKey.isSmall()); } else { - _masterNonspatialSet.insert(itemId); + _primaryNonspatialSet.insert(itemId); } } } @@ -323,9 +323,9 @@ void Scene::removeItems(const Transaction::Removes& transactions) { // Remove the item if (oldKey.isSpatial()) { - _masterSpatialTree.removeItem(oldCell, oldKey, removedID); + _primarySpatialTree.removeItem(oldCell, oldKey, removedID); } else { - _masterNonspatialSet.erase(removedID); + _primaryNonspatialSet.erase(removedID); } // Remove the transition to prevent updating it for nothing @@ -362,20 +362,20 @@ void Scene::updateItems(const Transaction::Updates& transactions) { // Update the item's container if (oldKey.isSpatial() == newKey.isSpatial()) { if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); + auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } } else { if (newKey.isSpatial()) { - _masterNonspatialSet.erase(updateID); + _primaryNonspatialSet.erase(updateID); - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); + auto newCell = _primarySpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } else { - _masterSpatialTree.removeItem(oldCell, oldKey, updateID); + _primarySpatialTree.removeItem(oldCell, oldKey, updateID); item.resetCell(); - _masterNonspatialSet.insert(updateID); + _primaryNonspatialSet.insert(updateID); } } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 19d56b61d2..988b04cc3f 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -185,10 +185,10 @@ public: const Item getItemSafe(const ItemID& id) const { if (isAllocatedID(id)) { return _items[id]; } else { return Item(); } } // Access the spatialized items - const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; } + const ItemSpatialTree& getSpatialTree() const { return _primarySpatialTree; } // Access non-spatialized items (layered objects, backgrounds) - const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } + const ItemIDSet& getNonspatialSet() const { return _primaryNonspatialSet; } // Access a particular Stage (empty if doesn't exist) // Thread safe @@ -226,8 +226,8 @@ protected: // database of items is protected for editing by a mutex std::mutex _itemsMutex; Item::Vector _items; - ItemSpatialTree _masterSpatialTree; - ItemIDSet _masterNonspatialSet; + ItemSpatialTree _primarySpatialTree; + ItemIDSet _primaryNonspatialSet; void resetItems(const Transaction::Resets& transactions); void resetTransitionFinishedOperator(const Transaction::TransitionFinishedOperators& transactions); diff --git a/libraries/script-engine/src/ScriptGatekeeper.cpp b/libraries/script-engine/src/ScriptGatekeeper.cpp index c223197a8c..43d9bbc0e2 100644 --- a/libraries/script-engine/src/ScriptGatekeeper.cpp +++ b/libraries/script-engine/src/ScriptGatekeeper.cpp @@ -19,21 +19,21 @@ void ScriptGatekeeper::initialize() { return; } - QVariant rawCurrentWhitelistValues = Setting::Handle(SCRIPT_WHITELIST_ENTRIES_KEY).get(); - QString settingsSafeValues = rawCurrentWhitelistValues.toString(); + QVariant rawCurrentAllowlistValues = Setting::Handle(SCRIPT_ALLOWLIST_ENTRIES_KEY).get(); + QString settingsSafeValues = rawCurrentAllowlistValues.toString(); - Setting::Handle whitelistEnabled { SCRIPT_WHITELIST_ENABLED_KEY, false }; + Setting::Handle allowlistEnabled { SCRIPT_ALLOWLIST_ENABLED_KEY, false }; Setting::Handle isFirstRun { Settings::firstRun, true }; - QString preloadedVal = BuildInfo::PRELOADED_SCRIPT_WHITELIST; + QString preloadedVal = BuildInfo::PRELOADED_SCRIPT_ALLOWLIST; if (settingsSafeValues.isEmpty() && !preloadedVal.isEmpty() && isFirstRun.get()) { - // We assume that the whitelist should be enabled if a preloaded whitelist is attached, so we activate it if it's not already active. - if (!whitelistEnabled.get()) { - whitelistEnabled.set(true); + // We assume that the allowlist should be enabled if a preloaded allowlist is attached, so we activate it if it's not already active. + if (!allowlistEnabled.get()) { + allowlistEnabled.set(true); } - Setting::Handle(SCRIPT_WHITELIST_ENTRIES_KEY).set(preloadedVal); + Setting::Handle(SCRIPT_ALLOWLIST_ENTRIES_KEY).set(preloadedVal); } _initialized = true; diff --git a/libraries/script-engine/src/ScriptGatekeeper.h b/libraries/script-engine/src/ScriptGatekeeper.h index 9f70900c9e..ed6b1ea2b6 100644 --- a/libraries/script-engine/src/ScriptGatekeeper.h +++ b/libraries/script-engine/src/ScriptGatekeeper.h @@ -17,14 +17,14 @@ #include -/// Manages script whitelisting in a domain +/// Manages script allowlisting in a domain class ScriptGatekeeper : public QObject { Q_OBJECT public: void initialize(); - QString SCRIPT_WHITELIST_ENABLED_KEY{ "private/whitelistEnabled" }; - QString SCRIPT_WHITELIST_ENTRIES_KEY{ "private/settingsSafeURLS" }; + QString SCRIPT_ALLOWLIST_ENABLED_KEY{ "private/allowlistEnabled" }; + QString SCRIPT_ALLOWLIST_ENTRIES_KEY{ "private/settingsSafeURLS" }; private: bool _initialized { false }; diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index db61d7144b..23122cc302 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -2192,17 +2192,17 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c exception = testConstructor; } } else { - // ENTITY SCRIPT WHITELIST STARTS HERE + // ENTITY SCRIPT ALLOWLIST STARTS HERE auto nodeList = DependencyManager::get(); bool passList = false; // assume unsafe - QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; + QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]"; QList safeURLPrefixes = { "file:///", "atp:", "cache:" }; - safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); + safeURLPrefixes += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); - // Entity Script Whitelist toggle check. - Setting::Handle whitelistEnabled {"private/whitelistEnabled", false }; + // Entity Script Allowlist toggle check. + Setting::Handle allowlistEnabled {"private/allowlistEnabled", false }; - if (!whitelistEnabled.get()) { + if (!allowlistEnabled.get()) { passList = true; } @@ -2212,39 +2212,39 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c safeURLPrefixes += settingsSafeURLS; // END Pull SAFEURLS from the Interface.JSON settings. - // Get current domain whitelist bypass, in case an entire domain is whitelisted. + // Get current domain allowlist bypass, in case an entire domain is allowlisted. QString currentDomain = DependencyManager::get()->getDomainURL().host(); QString domainSafeIP = nodeList->getDomainHandler().getHostname(); QString domainSafeURL = URL_SCHEME_OVERTE + "://" + currentDomain; for (const auto& str : safeURLPrefixes) { if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { - qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: " + qCDebug(scriptengine) << allowlistPrefix << "Allowlist Bypassed, entire domain is allowlisted. Current Domain Host: " << nodeList->getDomainHandler().getHostname() << "Current Domain: " << currentDomain; passList = true; } } - // END bypass whitelist based on current domain. + // END bypass allowlist based on current domain. - // Start processing scripts through the whitelist. - if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage whitelist. + // Start processing scripts through the allowlist. + if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage allowlist. passList = true; - } else if (!passList) { // If waved through, do not engage whitelist. + } else if (!passList) { // If waved through, do not engage allowlist. for (const auto& str : safeURLPrefixes) { - qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + qCDebug(scriptengine) << allowlistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); if (!str.isEmpty() && scriptOrURL.startsWith(str)) { passList = true; - qCDebug(scriptengine) << whitelistPrefix << "Script approved."; + qCDebug(scriptengine) << allowlistPrefix << "Script approved."; break; // Bail early since we found a match. } } } - // END processing of scripts through the whitelist. + // END processing of scripts through the allowlist. if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown. - qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; + qCDebug(scriptengine) << allowlistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = _engine->makeError(_engine->newValue("UNSAFE_ENTITY_SCRIPTS == 0")); } else { QTimer timeout; @@ -2267,7 +2267,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c exception = testConstructor; } } - // ENTITY SCRIPT WHITELIST ENDS HERE, uncomment below for original full disabling. + // ENTITY SCRIPT ALLOWLIST ENDS HERE, uncomment below for original full disabling. // qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL; // exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); @@ -2303,17 +2303,17 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c return; // done processing script }*/ - // ENTITY SCRIPT WHITELIST STARTS HERE + // ENTITY SCRIPT ALLOWLIST STARTS HERE auto nodeList = DependencyManager::get(); bool passList = false; // assume unsafe - QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]"; + QString allowlistPrefix = "[ALLOWLIST ENTITY SCRIPTS]"; QList safeURLPrefixes = { "file:///", "atp:", "cache:" }; - safeURLPrefixes += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); + safeURLPrefixes += qEnvironmentVariable("EXTRA_ALLOWLIST").trimmed().split(QRegExp("\\s*,\\s*"), Qt::SkipEmptyParts); - // Entity Script Whitelist toggle check. - Setting::Handle whitelistEnabled {"private/whitelistEnabled", false }; + // Entity Script Allowlist toggle check. + Setting::Handle allowlistEnabled {"private/allowlistEnabled", false }; - if (!whitelistEnabled.get()) { + if (!allowlistEnabled.get()) { passList = true; } @@ -2323,40 +2323,40 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c safeURLPrefixes += settingsSafeURLS; // END Pull SAFEURLS from the Interface.JSON settings. - // Get current domain whitelist bypass, in case an entire domain is whitelisted. + // Get current domain allowlist bypass, in case an entire domain is allowlisted. QString currentDomain = DependencyManager::get()->getDomainURL().host(); QString domainSafeIP = nodeList->getDomainHandler().getHostname(); QString domainSafeURL = URL_SCHEME_OVERTE + "://" + currentDomain; for (const auto& str : safeURLPrefixes) { if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { - qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: " + qCDebug(scriptengine) << allowlistPrefix << "Allowlist Bypassed, entire domain is allowlisted. Current Domain Host: " << nodeList->getDomainHandler().getHostname() << "Current Domain: " << currentDomain; passList = true; } } - // END bypass whitelist based on current domain. + // END bypass allowlist based on current domain. - // Start processing scripts through the whitelist. - if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage whitelist. + // Start processing scripts through the allowlist. + if (ScriptManager::getContext() == "entity_server") { // If running on the server, do not engage allowlist. passList = true; - } else if (!passList) { // If waved through, do not engage whitelist. + } else if (!passList) { // If waved through, do not engage allowlist. for (const auto& str : safeURLPrefixes) { - qCDebug(scriptengine) << whitelistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + qCDebug(scriptengine) << allowlistPrefix << "Script URL: " << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); if (!str.isEmpty() && scriptOrURL.startsWith(str)) { passList = true; - qCDebug(scriptengine) << whitelistPrefix << "Script approved."; + qCDebug(scriptengine) << allowlistPrefix << "Script approved."; break; // Bail early since we found a match. } } } - // END processing of scripts through the whitelist. + // END processing of scripts through the allowlist. ScriptValue exception; if (!passList) { // If the entity failed to pass for any reason, it's blocked and an error is thrown. - qCDebug(scriptengine) << whitelistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; + qCDebug(scriptengine) << allowlistPrefix << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = _engine->makeError(_engine->newValue("UNSAFE_ENTITY_SCRIPTS == 0")); } @@ -2369,7 +2369,7 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c emit unhandledException(scriptRuntimeException); return; } - // ENTITY SCRIPT WHITELIST ENDS HERE, uncomment below for original full disabling. + // ENTITY SCRIPT ALLOWLIST ENDS HERE, uncomment below for original full disabling. // qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL; // exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index b0c419e14b..76055253ab 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -110,17 +110,17 @@ public slots: bool getPersonalMuteStatus(const QUuid& nodeID); /*@jsdoc - * Sets an avatar's gain (volume) for you and you only, or sets the master gain. + * Sets an avatar's gain (volume) for you and you only, or sets the primary gain. * @function Users.setAvatarGain - * @param {Uuid} nodeID - The session ID of the avatar to set the gain for, or null to set the master gain. + * @param {Uuid} nodeID - The session ID of the avatar to set the gain for, or null to set the primary gain. * @param {number} gain - The gain to set, in dB. */ void setAvatarGain(const QUuid& nodeID, float gain); /*@jsdoc - * Gets an avatar's gain (volume) for you and you only, or gets the master gain. + * Gets an avatar's gain (volume) for you and you only, or gets the primary gain. * @function Users.getAvatarGain - * @param {Uuid} nodeID - The session ID of the avatar to get the gain for, or null to get the master gain. + * @param {Uuid} nodeID - The session ID of the avatar to get the gain for, or null to get the primary gain. * @returns {number} The gain, in dB. */ float getAvatarGain(const QUuid& nodeID); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index de350cd8ce..045f0a68c8 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -854,11 +854,11 @@ void printSystemInformation() { qCDebug(shared) << "Environment Variables"; // List of env variables to include in the log. For privacy reasons we don't send all env variables. - const QStringList envWhitelist = { + const QStringList envAllowlist = { "QTWEBENGINE_REMOTE_DEBUGGING" }; auto envVariables = QProcessEnvironment::systemEnvironment(); - for (auto& env : envWhitelist) + for (auto& env : envAllowlist) { qCDebug(shared).noquote().nospace() << "\t" << (envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND"); diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 9c80538e60..672ad74d36 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -28,7 +28,7 @@ const int NUM_FRUSTUM_CORNERS = 8; const int NUM_FRUSTUM_PLANES = 6; const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f; -const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; +const float DEFAULT_FIELD_OF_VIEW_DEGREES = 55.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; const float DEFAULT_NEAR_CLIP = 0.08f; const float DEFAULT_FAR_CLIP = 16384.0f; diff --git a/libraries/shared/src/WarningsSuppression.h b/libraries/shared/src/WarningsSuppression.h index a8459ac2e6..e2435055a4 100644 --- a/libraries/shared/src/WarningsSuppression.h +++ b/libraries/shared/src/WarningsSuppression.h @@ -19,7 +19,7 @@ */ -#ifdef OVERTE_WARNINGS_WHITELIST_GCC +#ifdef OVERTE_WARNINGS_ALLOWLIST_GCC #define OVERTE_IGNORE_DEPRECATED_BEGIN \ _Pragma("GCC diagnostic push") \ @@ -27,7 +27,7 @@ #define OVERTE_IGNORE_DEPRECATED_END _Pragma("GCC diagnostic pop") -#elif OVERTE_WARNINGS_WHITELIST_CLANG +#elif OVERTE_WARNINGS_ALLOWLIST_CLANG #define OVERTE_IGNORE_DEPRECATED_BEGIN \ _Pragma("clang diagnostic push") \ @@ -35,7 +35,7 @@ #define OVERTE_IGNORE_DEPRECATED_END _Pragma("clang diagnostic pop") -#elif OVERTE_WARNINGS_WHITELIST_MSVC +#elif OVERTE_WARNINGS_ALLOWLIST_MSVC #define OVERTE_IGNORE_DEPRECATED_BEGIN \ _Pragma("warning(push)") \ diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 88c7329a4f..8afcb80c45 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -63,11 +63,11 @@ namespace hifi { namespace qml { namespace offscreen { -class OffscreenQmlWhitelist : public Dependency, private ReadWriteLockable { +class OffscreenQmlAllowlist : public Dependency, private ReadWriteLockable { SINGLETON_DEPENDENCY public: - void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback) { + void addAllowlistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback) { withWriteLock([&] { for (auto url : urls) { if (url.isRelative()) { @@ -93,11 +93,11 @@ private: QHash> _callbacks; }; -QSharedPointer getQmlWhitelist() { +QSharedPointer getQmlAllowlist() { static std::once_flag once; - std::call_once(once, [&] { DependencyManager::set(); }); + std::call_once(once, [&] { DependencyManager::set(); }); - return DependencyManager::get(); + return DependencyManager::get(); } // Class to handle changing QML audio output device using another thread @@ -292,9 +292,9 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { engine->setObjectOwnership(tablet, QQmlEngine::CppOwnership); } -void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list& urls, +void OffscreenQmlSurface::addAllowlistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback) { - getQmlWhitelist()->addWhitelistContextHandler(urls, callback); + getQmlAllowlist()->addAllowlistContextHandler(urls, callback); } void OffscreenQmlSurface::onRootContextCreated(QQmlContext* qmlContext) { @@ -319,17 +319,17 @@ void OffscreenQmlSurface::onRootContextCreated(QQmlContext* qmlContext) { #endif } -void OffscreenQmlSurface::applyWhiteList(const QUrl& url, QQmlContext* context) { - QList callbacks = getQmlWhitelist()->getCallbacksForUrl(url); +void OffscreenQmlSurface::applyAllowList(const QUrl& url, QQmlContext* context) { + QList callbacks = getQmlAllowlist()->getCallbacksForUrl(url); for(const auto& callback : callbacks){ callback(context); } } QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, QQuickItem* parent, bool forceNewContext) { - // Get any whitelist functionality - QList callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource); - // If we have whitelisted content, we must load a new context + // Get any allowlist functionality + QList callbacks = getQmlAllowlist()->getCallbacksForUrl(qmlSource); + // If we have allowlisted content, we must load a new context forceNewContext |= !callbacks.empty(); QQmlContext* targetContext = Parent::contextForUrl(qmlSource, parent, forceNewContext); diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h index 6b0971bb8a..07358dcf38 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.h +++ b/libraries/ui/src/ui/OffscreenQmlSurface.h @@ -28,9 +28,9 @@ class OffscreenQmlSurface : public hifi::qml::OffscreenSurface { public: ~OffscreenQmlSurface(); - static void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback); - static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); }; - static void applyWhiteList(const QUrl& url,QQmlContext* context); + static void addAllowlistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback); + static void addAllowlistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addAllowlistContextHandler({ { url } }, callback); }; + static void applyAllowList(const QUrl& url,QQmlContext* context); bool isFocusText() const { return _focusText; } bool getCleaned() { return _isCleaned; } diff --git a/libraries/ui/src/ui/types/RequestFilters.cpp b/libraries/ui/src/ui/types/RequestFilters.cpp index ceac3d00e8..601cf56d6c 100644 --- a/libraries/ui/src/ui/types/RequestFilters.cpp +++ b/libraries/ui/src/ui/types/RequestFilters.cpp @@ -54,7 +54,7 @@ namespace { return false; } - // We can potentially add whitelisting logic or development environment variables that + // We can potentially add allowlisting logic or development environment variables that // will allow people to override this setting on a per-client basis here. QString targetFilePath = QFileInfo(requestUrl.toLocalFile()).canonicalFilePath(); diff --git a/pkg-scripts/make-rpm-server b/pkg-scripts/make-rpm-server index cf84bb97f2..2767b3b8c5 100755 --- a/pkg-scripts/make-rpm-server +++ b/pkg-scripts/make-rpm-server @@ -13,7 +13,8 @@ fi # The regex below extracts the path from the VCPKG_INSTALL_ROOT variable. Said variable gets populated during the CMake step. VCPKG_INSTALL_ROOT=`grep VCPKG_INSTALL_ROOT $OVERTE/build/vcpkg.cmake | perl -ne 'm/set\(VCPKG_INSTALL_ROOT\s+\"(.*?)\"/; print $1'` -VERSION=${RPMVERSION} +# Remove minus character from version numbers, because rpmtool doesn't allow them. +VERSION=${RPMVERSION//-} if [ "$OVERTE_USE_SYSTEM_QT" = "" ]; then SOFILES=`ls \ diff --git a/scripts/communityScripts/chat/FloofChat.html b/script-archive/floofChat/FloofChat.html similarity index 100% rename from scripts/communityScripts/chat/FloofChat.html rename to script-archive/floofChat/FloofChat.html diff --git a/scripts/communityScripts/chat/FloofChat.js b/script-archive/floofChat/FloofChat.js similarity index 100% rename from scripts/communityScripts/chat/FloofChat.js rename to script-archive/floofChat/FloofChat.js diff --git a/scripts/communityScripts/chat/FloofChat.qml b/script-archive/floofChat/FloofChat.qml similarity index 100% rename from scripts/communityScripts/chat/FloofChat.qml rename to script-archive/floofChat/FloofChat.qml diff --git a/scripts/communityScripts/chat/chat.png b/script-archive/floofChat/chat.png similarity index 100% rename from scripts/communityScripts/chat/chat.png rename to script-archive/floofChat/chat.png diff --git a/scripts/communityScripts/chat/css/FloofChat.css b/script-archive/floofChat/css/FloofChat.css similarity index 100% rename from scripts/communityScripts/chat/css/FloofChat.css rename to script-archive/floofChat/css/FloofChat.css diff --git a/scripts/communityScripts/chat/css/materialize.css b/script-archive/floofChat/css/materialize.css similarity index 100% rename from scripts/communityScripts/chat/css/materialize.css rename to script-archive/floofChat/css/materialize.css diff --git a/scripts/communityScripts/chat/js/materialize.min.js b/script-archive/floofChat/js/materialize.min.js similarity index 100% rename from scripts/communityScripts/chat/js/materialize.min.js rename to script-archive/floofChat/js/materialize.min.js diff --git a/scripts/communityScripts/chat/resources/bubblepop.wav b/script-archive/floofChat/resources/bubblepop.wav similarity index 100% rename from scripts/communityScripts/chat/resources/bubblepop.wav rename to script-archive/floofChat/resources/bubblepop.wav diff --git a/scripts/system/html/ChatPage.html b/script-archive/systemChat/ChatPage.html similarity index 100% rename from scripts/system/html/ChatPage.html rename to script-archive/systemChat/ChatPage.html diff --git a/scripts/system/chat.js b/script-archive/systemChat/chat.js similarity index 99% rename from scripts/system/chat.js rename to script-archive/systemChat/chat.js index 94a26dc632..14696946b3 100644 --- a/scripts/system/chat.js +++ b/script-archive/systemChat/chat.js @@ -4,7 +4,7 @@ // // By Don Hopkins (dhopkins@donhopkins.com) on May 5th, 2017 // Copyright 2017 High Fidelity, Inc. -// Copyright 2023 Overte e.V. +// Copyright 2024 Overte e.V. // // // Distributed under the Apache License, Version 2.0. @@ -13,7 +13,7 @@ (function() { - var webPageURL = Script.resolvePath("html/ChatPage.html"); // URL of tablet web page. + var webPageURL = Script.resolvePath("ChatPage.html"); // URL of tablet web page. var randomizeWebPageURL = true; // Set to true for debugging. var lastWebPageURL = ""; // Last random URL of tablet web page. var onChatPage = false; // True when chat web page is opened. diff --git a/scripts/communityScripts/armored-chat/README.md b/scripts/communityScripts/armored-chat/README.md new file mode 100644 index 0000000000..2385494676 --- /dev/null +++ b/scripts/communityScripts/armored-chat/README.md @@ -0,0 +1,205 @@ +# Armored Chat + +1. What is Armored Chat +2. User manual + - Installation + - Settings + - Usability tips +3. Development + +## What is Armored Chat + +Armored Chat is a chat application strictly made to communicate between players in the same domain. It is made using QML and to be as light weight as reasonably possible. + +### Dependencies + +AC uses the Overte [Messages](https://apidocs.overte.org/Messages.html) API to communicate. + +For notifications, AC uses [notificationCore.js](https://github.com/overte-org/overte/blob/bb8bac43eadd3b20956a2ff7b0b21c28844b0f77/scripts/communityScripts/notificationCore/notificationCore.js). + +## User manual + +### Installation + +Armored Chat is preinstalled courtesy of [defaultScripts.js](https://github.com/overte-org/overte/blob/8661e8a858663b48e8485c2cd7120dc3e2d7b87e/scripts/defaultScripts.js). + +If AC is not preinstalled, or for some other reason it can not be automatically installed, you can install it manually by following [these instructions](https://github.com/overte-org/overte/blob/8661e8a858663b48e8485c2cd7120dc3e2d7b87e/scripts/defaultScripts.js) to open your script management application, and loading the script url: + +``` +https://raw.githubusercontent.com/overte-org/overte/master/scripts/communityScripts/armored-chat/armored_chat.js +``` + +--- + +### Settings + +Armored Chat comes with basic settings for managing itself. + +#### External window + +This boolean setting toggles whether AC will be a in-game overlay window, or whether AC will be a external floating window. + +Default is `false`. + +#### Maximum saved messages + +This integer represents the amount of messages to save in the AC history. More messages may be present if AC is left on long enough. This setting only sets the number of saved messages and not the maximum amount of messages that can be viewed at any time. + +This means if you set the value to `5`, your history will save a maximum of 5 messages, however you will still be able to see a longer history in the session should you receive more. Once AC completely closes and fetches your message history as it initializes, you will only see the last 5 messages. + +Default value is `200` + +#### Erase chat history + +This action immediately clears the AC history and the session. Functionally this will set the message list to a empty Array. + +### Usage + +AC has two chat modes: Local, and Domain. Local chat displays all other local chat messages that are within 20 units of you. Domain chat will display all other Domain messages sent though that channel regardless of distance. + +AC also handles link embedding. When you send an HTTP(S) link, it will automatically parse it using Qt RichText and allow everyone to click on the message. Next to the link you will also see a "⮺" symbol. Clicking on this symbol will open the link in an external window. + +### Usability tips + +#### Navigation + +You can scroll quickly using kinetic scrolling! Try "grabbing" the right side of messages, where the timestamp is, and flinging yourself in a direction. + +#### Formatting + +You can format messages using basic HTML elements. Try `
Red text!
` to color your text red. +Find the full list of Qt rich text tags [here](https://doc.qt.io/qt-6/richtext-html-subset.html). Please note that some of these tags may be intentionally restricted. + +#### Media embedding + +Images can be embedded when linked directly. + +Try it out by linking to the Overte logo! `https://github.com/overte-org/overte/raw/master/interface/resources/images/brand-banner.svg` + +In order for images to be embedded, URLs must end in a image filetype. +Supported filetypes are: + +- `.png` +- `.jpg` +- `.jpeg` +- `.gif` +- `.bmp` +- `.svg` +- `.webp` + +## Development + +### To QML communication + +Here are the signals needed to communicate from the JavaScript core to the QML interface. + +AC calls a `_emitEvent()` function that also includes a `type` key in the object. This `type` tells the QML and/or the JS core what the packet is for. +When you call the `_emitEvent()` function be sure to include the following signals as a `type`. In the examples below, the `type` is being excluded for brevity. + +Example: + +```json +{ type: "show_message", displayName: "username", ...} +``` + +#### "show_message" + +This signal tells the QML to add a new message to the ListView element list. + +Supply a `JSON` object. + +```json +{ + "displayName": "username", + "message": "chat message", + "channel": "domain", // Channel to send message on. By default it should only be "domain" or "local". + "date": "[ time and date string ]" // Optional, defaults to current time and date. +} +``` + +#### "clear_messages" + +Clear all messages displayed in the ListView elements. Note this does not clear the history and this is only a visual erasure. + +No payload required. + +#### "notification" + +Renders a notification to the domain channel. +The intended use is to provide updates about the domain and make the notifications accessible. + +Supply a `JSON` object. + +```json +{ + "message": "notification message" // Notification to render +} +``` + +#### "initial_settings" + +Visually set the settings in the QML interface based on the supplied object. + +Supply a `JSON` object. + +```json +{ + "settings": { + // JSON object of current AC settings + "external_window": false, + "maximum_messages": 200 + } +} +``` + +### To JS communication + +Here are the signals needed to communicate from the QML interface to the JavaScript core. AC is developed in a way that all actions that are not style related are preformed though the JavaScript core. +This means that what ever action you want to preform must go though the JavaScript core for processing. + +This is formatted the same was as the communication packets to the QML interface. Supply the following entries as "type"s in your packet. + +#### "send_message" + +Tell AC to broadcast a message to the domain. + +Supply a `JSON` object. + +```json +{ + "message": "message content", // The contents of the message to send. + "channel": "domain" // Channel to emit the message to. +} +``` + +#### "setting_change" + +Tell AC to change a setting. Exercise caution when using this as you can add new settings unintentionally if you are not careful. + +Supply a `JSON` object + +```json +{ + "setting": "external_window", // The name of the setting to change + "value": true // The value to change the setting to +} +``` + +#### "action" + +Tell AC to preform a generic action. This is normally reserved for functions that would get called on a button onClicked event in the QML. + +Supply a `JSON` object + +```json +{ + "action": "erase_history" // The action to preform +} +``` + +#### "initialized" + +Tell AC the QML overlay has loaded successfully. +This is called to hide the overlay on creation. + +No payload required. diff --git a/scripts/communityScripts/armored-chat/armored_chat.js b/scripts/communityScripts/armored-chat/armored_chat.js new file mode 100644 index 0000000000..fe66da7a54 --- /dev/null +++ b/scripts/communityScripts/armored-chat/armored_chat.js @@ -0,0 +1,291 @@ +// +// armored_chat.js +// +// Created by Armored Dragon, 2024. +// Copyright 2024 Overte e.V. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +(() => { + ("use strict"); + + var appIsVisible = false; + var settings = { + external_window: false, + maximum_messages: 200, + }; + + // Global vars + var tablet; + var chatOverlayWindow; + var appButton; + var quickMessage; + const channels = ["domain", "local"]; + var messageHistory = Settings.getValue("ArmoredChat-Messages", []) || []; + var maxLocalDistance = 20; // Maximum range for the local chat + var palData = AvatarManager.getPalData().data; + + Controller.keyPressEvent.connect(keyPressEvent); + Messages.subscribe("Chat"); // Floofchat + Messages.subscribe("chat"); + Messages.messageReceived.connect(receivedMessage); + AvatarManager.avatarAddedEvent.connect((sessionId) => { + _avatarAction("connected", sessionId); + }); + AvatarManager.avatarRemovedEvent.connect((sessionId) => { + _avatarAction("left", sessionId); + }); + + startup(); + + function startup() { + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + appButton = tablet.addButton({ + icon: Script.resolvePath("./img/icon_white.png"), + activeIcon: Script.resolvePath("./img/icon_black.png"), + text: "CHAT", + isActive: appIsVisible, + }); + + // When script ends, remove itself from tablet + Script.scriptEnding.connect(function () { + console.log("Shutting Down"); + tablet.removeButton(appButton); + chatOverlayWindow.close(); + }); + + // Overlay button toggle + appButton.clicked.connect(toggleMainChatWindow); + + quickMessage = new OverlayWindow({ + source: Script.resolvePath("./armored_chat_quick_message.qml"), + }); + + _openWindow(); + } + function toggleMainChatWindow() { + appIsVisible = !appIsVisible; + appButton.editProperties({ isActive: appIsVisible }); + chatOverlayWindow.visible = appIsVisible; + + // External window was closed; the window does not exist anymore + if (chatOverlayWindow.title == "" && appIsVisible) { + _openWindow(); + } + } + function _openWindow() { + chatOverlayWindow = new Desktop.createWindow( + Script.resolvePath("./armored_chat.qml"), + { + title: "Chat", + size: { x: 550, y: 400 }, + additionalFlags: Desktop.ALWAYS_ON_TOP, + visible: appIsVisible, + presentationMode: Desktop.PresentationMode.VIRTUAL, + } + ); + + chatOverlayWindow.closed.connect(toggleMainChatWindow); + chatOverlayWindow.fromQml.connect(fromQML); + quickMessage.fromQml.connect(fromQML); + } + function receivedMessage(channel, message) { + // Is the message a chat message? + channel = channel.toLowerCase(); + if (channel !== "chat") return; + message = JSON.parse(message); + + if (!message.channel) message.channel = "domain"; // We don't know where to put this message. Assume it is a domain wide message. + if (message.forApp) return; // Floofchat + + // Floofchat compatibility hook + message = floofChatCompatibilityConversion(message); + message.channel = message.channel.toLowerCase(); // Make sure the "local", "domain", etc. is formatted consistently + + if (!channels.includes(message.channel)) return; // Check the channel + if ( + message.channel == "local" && + Vec3.distance(MyAvatar.position, message.position) > + maxLocalDistance + ) + return; // If message is local, and if player is too far away from location, don't do anything + + // Update qml view of to new message + _emitEvent({ type: "show_message", ...message }); + + Messages.sendLocalMessage( + "Floof-Notif", + JSON.stringify({ + sender: message.displayName, + text: message.message, + }) + ); + + // Save message to history + let savedMessage = message; + delete savedMessage.position; + savedMessage.timeString = new Date().toLocaleTimeString(undefined, { + hour12: false, + }); + savedMessage.dateString = new Date().toLocaleDateString(undefined, { + year: "numeric", + month: "long", + day: "numeric", + }); + messageHistory.push(savedMessage); + while (messageHistory.length > settings.maximum_messages) { + messageHistory.shift(); + } + Settings.setValue("ArmoredChat-Messages", messageHistory); + } + function fromQML(event) { + switch (event.type) { + case "send_message": + _sendMessage(event.message, event.channel); + break; + case "setting_change": + settings[event.setting] = event.value; // Update local settings + _saveSettings(); // Save local settings + + switch (event.setting) { + case "external_window": + chatOverlayWindow.presentationMode = event.value + ? Desktop.PresentationMode.NATIVE + : Desktop.PresentationMode.VIRTUAL; + break; + case "maximum_messages": + // Do nothing + break; + } + + break; + case "action": + switch (event.action) { + case "erase_history": + Settings.setValue("ArmoredChat-Messages", []); + _emitEvent({ + type: "clear_messages", + }); + break; + } + break; + case "initialized": + // https://github.com/overte-org/overte/issues/824 + chatOverlayWindow.visible = appIsVisible; // The "visible" field in the Desktop.createWindow does not seem to work. Force set it to the initial state (false) + _loadSettings(); + break; + } + } + function keyPressEvent(event) { + switch (JSON.stringify(event.key)) { + case "16777220": // Enter key + if (HMD.active) return; // Don't allow in VR + + quickMessage.sendToQml({ + type: "change_visibility", + value: true, + }); + } + } + function _sendMessage(message, channel) { + if (message.length == 0) return; + + Messages.sendMessage( + "chat", + JSON.stringify({ + position: MyAvatar.position, + message: message, + displayName: MyAvatar.sessionDisplayName, + channel: channel, + action: "send_chat_message", + }) + ); + + floofChatCompatibilitySendMessage(message, channel); + } + function _avatarAction(type, sessionId) { + Script.setTimeout(() => { + if (type == "connected") { + palData = AvatarManager.getPalData().data; + } + + // Get the display name of the user + let displayName = ""; + displayName = + AvatarManager.getPalData([sessionId])?.data[0] + ?.sessionDisplayName || null; + if (displayName == null) { + for (let i = 0; i < palData.length; i++) { + if (palData[i].sessionUUID == sessionId) { + displayName = palData[i].sessionDisplayName; + } + } + } + + // Format the packet + let message = {}; + message.message = `${displayName} ${type}`; + + _emitEvent({ type: "notification", ...message }); + }, 1500); + } + function _loadSettings() { + settings = Settings.getValue("ArmoredChat-Config", settings); + + if (messageHistory) { + // Load message history + messageHistory.forEach((message) => { + delete message.action; + _emitEvent({ type: "show_message", ...message }); + }); + } + + // Send current settings to the app + _emitEvent({ type: "initial_settings", settings: settings }); + } + function _saveSettings() { + console.log("Saving config"); + Settings.setValue("ArmoredChat-Config", settings); + } + + /** + * Emit a packet to the HTML front end. Easy communication! + * @param {Object} packet - The Object packet to emit to the HTML + * @param {("show_message"|"clear_messages"|"notification"|"initial_settings")} packet.type - The type of packet it is + */ + function _emitEvent(packet = { type: "" }) { + chatOverlayWindow.sendToQml(packet); + } + + // + // Floofchat compatibility functions + // Added to ease the transition between Floofchat to ArmoredChat + // These functions can be safely removed at a much later date. + function floofChatCompatibilityConversion(message) { + if (message.type === "TransmitChatMessage" && !message.forApp) { + return { + position: message.position, + message: message.message, + displayName: message.displayName, + channel: message.channel.toLowerCase(), + }; + } + return message; + } + + function floofChatCompatibilitySendMessage(message, channel) { + Messages.sendMessage( + "Chat", + JSON.stringify({ + position: MyAvatar.position, + message: message, + displayName: MyAvatar.sessionDisplayName, + channel: channel.charAt(0).toUpperCase() + channel.slice(1), + type: "TransmitChatMessage", + forApp: "Floof", + }) + ); + } +})(); diff --git a/scripts/communityScripts/armored-chat/armored_chat.qml b/scripts/communityScripts/armored-chat/armored_chat.qml new file mode 100644 index 0000000000..91018502dd --- /dev/null +++ b/scripts/communityScripts/armored-chat/armored_chat.qml @@ -0,0 +1,570 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import controlsUit 1.0 as HifiControlsUit + +Rectangle { + color: Qt.rgba(0.1,0.1,0.1,1) + signal sendToScript(var message); + + property string pageVal: "local" + property string last_message_user: "" + property date last_message_time: new Date() + + // When the window is created on the script side, the window starts open. + // Once the QML window is created wait, then send the initialized signal. + // This signal is mostly used to close the "Desktop overlay window" script side + // https://github.com/overte-org/overte/issues/824 + Timer { + interval: 10 + running: true + repeat: false + onTriggered: { + toScript({type: "initialized"}); + load_scroll_timer.running = true + } + } + Timer { + id: load_scroll_timer + interval: 100 + running: false + repeat: false + onTriggered: { + scrollToBottom(); + } + } + + // User view + Item { + anchors.fill: parent + + // Navigation Bar + Rectangle { + id: navigation_bar + width: parent.width + height: 40 + color:Qt.rgba(0,0,0,1) + + Item { + height: parent.height + width: parent.width + anchors.fill: parent + + Rectangle { + width: pageVal === "local" ? 100 : 60 + height: parent.height + color: pageVal === "local" ? "#505186" : "white" + id: local_page + + Image { + source: "./img/ui/" + (pageVal === "local" ? "social_white.png" : "social_black.png") + sourceSize.width: 40 + sourceSize.height: 40 + anchors.centerIn: parent + } + + Behavior on width { + NumberAnimation { + duration: 50 + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + pageVal = "local"; + load_scroll_timer.running = true; + } + } + } + Rectangle { + width: pageVal === "domain" ? 100 : 60 + height: parent.height + color: pageVal === "domain" ? "#505186" : "white" + anchors.left: local_page.right + anchors.leftMargin: 5 + id: domain_page + + Image { + source: "./img/ui/" + (pageVal === "domain" ? "world_white.png" : "world_black.png") + sourceSize.width: 30 + sourceSize.height: 30 + anchors.centerIn: parent + } + + Behavior on width { + NumberAnimation { + duration: 50 + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + pageVal = "domain" + load_scroll_timer.running = true; + } + } + } + + Rectangle { + width: pageVal === "settings" ? 100 : 60 + height: parent.height + color: pageVal === "settings" ? "#505186" : "white" + anchors.right: parent.right + id: settings_page + + Image { + source: "./img/ui/" + (pageVal === "settings" ? "settings_white.png" : "settings_black.png") + sourceSize.width: 30 + sourceSize.height: 30 + anchors.centerIn: parent + } + + Behavior on width { + NumberAnimation { + duration: 50 + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + pageVal = "settings" + } + } + } + } + + } + + // Pages + Item { + width: parent.width + height: parent.height - 40 + anchors.top: navigation_bar.bottom + visible: ["local", "domain"].includes(pageVal) ? true : false + + + // Chat Message History + ListView { + width: parent.width + height: parent.height - 40 + clip: true + interactive: true + spacing: 5 + id: listview + + delegate: Loader { + property int delegateIndex: index + property string delegateText: model.text + property string delegateUsername: model.username + property string delegateDate: model.date + width: listview.width + + sourceComponent: { + if (model.type === "chat") { + return template_chat_message; + } else if (model.type === "notification") { + return template_notification; + } + } + } + + ScrollBar.vertical: ScrollBar { + id: chat_scrollbar + height: 100 + size: 0.05 + } + + model: getChannel(pageVal) + + } + + ListModel { + id: local + } + + ListModel { + id: domain + } + + // Chat Entry + Rectangle { + width: parent.width + height: 40 + color: Qt.rgba(0.9,0.9,0.9,1) + anchors.bottom: parent.bottom + + Row { + width: parent.width + height: parent.height + + TextField { + width: parent.width - 60 + height: parent.height + placeholderText: pageVal.charAt(0).toUpperCase() + pageVal.slice(1) + " chat message..." + clip: false + Keys.onPressed: { + if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && !(event.modifiers & Qt.ShiftModifier)) { + event.accepted = true; + toScript({type: "send_message", message: text, channel: pageVal}); + text = "" + } + } + onFocusChanged: { + if (!HMD.active) return; + if (focus) return ApplicationInterface.showVRKeyboardForHudUI(true); + ApplicationInterface.showVRKeyboardForHudUI(false); + } + } + Button { + width: 60 + height:parent.height + + Image { + source: "./img/ui/send_black.png" + sourceSize.width: 30 + sourceSize.height: 30 + anchors.centerIn: parent + } + + onClicked: { + toScript({type: "send_message", message: parent.children[0].text, channel: pageVal}); + parent.children[0].text = "" + } + Keys.onPressed: { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + toScript({type: "send_message", message: parent.children[0].text, channel: pageVal}); + parent.children[0].text = "" + } + } + } + } + } + } + + Item { + width: parent.width + height: parent.height - 40 + anchors.top: navigation_bar.bottom + visible: ["local", "domain"].includes(pageVal) ? false : true + + Column { + width: parent.width - 10 + height: parent.height - 10 + anchors.centerIn: parent + spacing: 10 + + // External Window + Rectangle { + width: parent.width + height: 40 + color: "transparent" + + Text{ + text: "External window" + color: "white" + font.pointSize: 12 + anchors.verticalCenter: parent.verticalCenter + } + + CheckBox{ + id: s_external_window + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + onCheckedChanged: { + toScript({type: 'setting_change', setting: 'external_window', value: checked}) + } + } + } + + // Maximum saved messages + Rectangle { + width: parent.width + height: 40 + color: "transparent" + + Text{ + text: "Maximum saved messages" + color: "white" + font.pointSize: 12 + anchors.verticalCenter: parent.verticalCenter + } + + + HifiControlsUit.SpinBox { + id: s_maximum_messages + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + decimals: 0 + width: 100 + height: parent.height + realFrom: 1 + realTo: 1000 + backgroundColor: "#cccccc" + + onValueChanged: { + toScript({type: 'setting_change', setting: 'maximum_messages', value: value}) + } + } + } + + // Erase History + Rectangle { + width: parent.width + height: 40 + color: Qt.rgba(0.15,0.15,0.15,1); + + Text{ + text: "Erase chat history" + color: "white" + font.pointSize: 12 + anchors.verticalCenter: parent.verticalCenter + } + + Button { + anchors.right: parent.right + text: "Erase" + height: parent.height + anchors.verticalCenter: parent.verticalCenter + + onClicked: { + toScript({type: "action", action: "erase_history"}) + } + } + } + } + } + + } + + // Templates + Component { + id: template_chat_message + + Rectangle{ + property int index: delegateIndex + property string texttest: delegateText + property string username: delegateUsername + property string date: delegateDate + + height: Math.max(65, children[1].height + 30) + color: index % 2 === 0 ? "transparent" : Qt.rgba(0.15,0.15,0.15,1) + + Item { + width: parent.width - 10 + anchors.horizontalCenter: parent.horizontalCenter + height: 22 + + Text{ + text: username + color: "lightgray" + } + + Text{ + anchors.right: parent.right + text: date + color: "lightgray" + } + } + + TextEdit{ + anchors.top: parent.children[0].bottom + x: 5 + text: texttest + color:"white" + font.pointSize: 12 + readOnly: true + selectByMouse: true + selectByKeyboard: true + width: parent.width * 0.8 + height: contentHeight + wrapMode: Text.Wrap + textFormat: TextEdit.RichText + + onLinkActivated: { + Window.openWebBrowser(link) + } + } + } + } + + Component { + id: template_notification + + Rectangle{ + property int index: delegateIndex + property string texttest: delegateText + property string username: delegateUsername + property string date: delegateDate + color: "#171717" + width: parent.width + height: 40 + + Item { + width: 10 + height: parent.height + + Rectangle { + height: parent.height + width: 5 + color: "#505186" + } + } + + + Item { + width: parent.width - parent.children[0].width - 5 + height: parent.height + anchors.left: parent.children[0].right + + TextEdit{ + text: texttest + color:"white" + font.pointSize: 12 + readOnly: true + width: parent.width * 0.8 + selectByMouse: true + selectByKeyboard: true + height: parent.height + wrapMode: Text.Wrap + verticalAlignment: Text.AlignVCenter + font.italic: true + } + + Text { + text: date + color:"white" + font.pointSize: 12 + anchors.right: parent.right + height: parent.height + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + font.italic: true + } + } + + } + + } + + + + property var channels: { + "local": local, + "domain": domain, + } + + function scrollToBottom() { + if (listview.count == 0) return; + listview.positionViewAtEnd(); + } + + + function addMessage(username, message, date, channel, type){ + channel = getChannel(channel) + + // Format content + message = formatContent(message); + + message = embedImages(message); + + if (type === "notification"){ + channel.append({ text: message, date: date, type: "notification" }); + last_message_user = ""; + scrollToBottom(); + last_message_time = new Date(); + return; + } + + var current_time = new Date(); + var elapsed_time = current_time - last_message_time; + var elapsed_minutes = elapsed_time / (1000 * 60); + + var last_item_index = channel.count - 1; + var last_item = channel.get(last_item_index); + + // FIXME: When adding a new message this would check to see if we could append the incoming message + // to the bottom of the last message. This current implimentation causes issues with scrollToBottom() + // Specifically, scrolling to the bottom does not like image embeds. + // This needs to be reworked entirely before it can be reimplimented + // if (last_message_user === username && elapsed_minutes < 1 && last_item){ + // message = "
" + message + // last_item.text = last_item.text += "\n" + message; + // scrollToBottom() + // last_message_time = new Date(); + // return; + // } + + last_message_user = username; + last_message_time = new Date(); + channel.append({ text: message, username: username, date: date, type: type }); + scrollToBottom(); + } + + function getChannel(id) { + return channels[id]; + } + + function formatContent(mess) { + var arrow = /\ {return `` + match + ` `}); + + var newline = /\n/gi; + mess = mess.replace(newline, "
"); + return mess + } + + function embedImages(mess){ + var image_link = /(https?:(\/){2})[\w.-]+(?:\.[\w\.-]+)+(?:\/[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]*)(?:png|jpe?g|gif|bmp|svg|webp)/g; + var matches = mess.match(image_link); + var new_message = "" + var listed = [] + var total_emeds = 0 + + new_message += mess + + for (var i = 0; matches && matches.length > i && total_emeds < 3; i++){ + if (!listed.includes(matches[i])) { + new_message += "
" + listed.push(matches[i]); + total_emeds++ + } + } + return new_message; + } + + // Messages from script + function fromScript(message) { + let time = new Date().toLocaleTimeString(undefined, { hour12: false }); + let date = new Date().toLocaleDateString(undefined, { year: "numeric", month: "long", day: "numeric", }); + + switch (message.type){ + case "show_message": + addMessage(message.displayName, message.message, `[ ${message.timeString || time} - ${message.dateString || date} ]`, message.channel, "chat"); + break; + case "notification": + addMessage("SYSTEM", message.message, `[ ${time} - ${date} ]`, "domain", "notification"); + break; + case "clear_messages": + local.clear(); + domain.clear(); + break; + case "initial_settings": + if (message.settings.external_window) s_external_window.checked = true; + if (message.settings.maximum_messages) s_maximum_messages.value = message.settings.maximum_messages; + break; + } + } + + // Send message to script + function toScript(packet){ + sendToScript(packet) + } +} diff --git a/scripts/communityScripts/armored-chat/armored_chat_quick_message.qml b/scripts/communityScripts/armored-chat/armored_chat_quick_message.qml new file mode 100644 index 0000000000..ae110db379 --- /dev/null +++ b/scripts/communityScripts/armored-chat/armored_chat_quick_message.qml @@ -0,0 +1,112 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + id: root + property var window + + Binding { target: root; property:'window'; value: parent.parent; when: Boolean(parent.parent) } + Binding { target: window; property: 'shown'; value: false; when: Boolean(window) } + Component.onDestruction: chat_bar && chat_bar.destroy() + + property alias chat_bar: chat_bar + + Rectangle { + id: chat_bar + parent: desktop + x: 0 + y: parent.height - height + width: parent.width + height: 50 + z: 99 + visible: false + + TextArea { + id: textArea + x: 0 + width: parent.width + height: parent.height + text:"" + textColor: "#ffffff" + clip: false + font.pointSize: 18 + + Keys.onReturnPressed: { _onEnterPressed(); } + Keys.onEnterPressed: { _onEnterPressed(); } + Keys.onLeftPressed: { moveLeft(); } + Keys.onRightPressed: { moveRight(); } + + function moveLeft(){ + if (cursorPosition > 0){ + cursorPosition-- + } + } + function moveRight(){ + if (cursorPosition < text.length){ + cursorPosition++ + } + } + } + + Text { + text: "Local message..." + font.pointSize: 16 + color: "gray" + x: 0 + width: parent.width + anchors.verticalCenter: parent.verticalCenter + visible: textArea.text == "" + } + + Button { + id: button + x: parent.width - width + y: 0 + width: 64 + height: parent.height + clip: false + visible: true + + Image { + id: image + width: 30 + height: 30 + fillMode: Image.PreserveAspectFit + visible: true + anchors.centerIn: parent + source: "./img/ui/send_white.png" + } + + onClicked: { + _onEnterPressed(); + } + } + + } + + function _onEnterPressed() { + changeVisibility(false) + toScript({type: "send_message", message: textArea.text, channel: "local"}) + textArea.text = ""; + } + + function changeVisibility(state){ + chat_bar.visible = state + if (state) textArea.forceActiveFocus(); + else root.parent.forceActiveFocus(); + } + + // Messages from script + function fromScript(message) { + switch (message.type){ + case "change_visibility": + changeVisibility(message.value) + break; + } + } + + // Send message to script + function toScript(packet){ + sendToScript(packet) + } +} \ No newline at end of file diff --git a/scripts/communityScripts/armored-chat/img/icon_black.png b/scripts/communityScripts/armored-chat/img/icon_black.png new file mode 100644 index 0000000000..410dc40b59 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/icon_black.png differ diff --git a/scripts/communityScripts/armored-chat/img/icon_white.png b/scripts/communityScripts/armored-chat/img/icon_white.png new file mode 100644 index 0000000000..e29bf99706 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/icon_white.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/send.svg b/scripts/communityScripts/armored-chat/img/ui/send.svg new file mode 100644 index 0000000000..82c70a6daf --- /dev/null +++ b/scripts/communityScripts/armored-chat/img/ui/send.svg @@ -0,0 +1,42 @@ + + + + + + diff --git a/scripts/communityScripts/armored-chat/img/ui/send_black.png b/scripts/communityScripts/armored-chat/img/ui/send_black.png new file mode 100644 index 0000000000..bc9ece7a11 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/send_black.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/send_white.png b/scripts/communityScripts/armored-chat/img/ui/send_white.png new file mode 100644 index 0000000000..2730d2f84c Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/send_white.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/settings_black.png b/scripts/communityScripts/armored-chat/img/ui/settings_black.png new file mode 100644 index 0000000000..f6481a85f8 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/settings_black.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/settings_white.png b/scripts/communityScripts/armored-chat/img/ui/settings_white.png new file mode 100644 index 0000000000..12a35ad58c Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/settings_white.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/social_black.png b/scripts/communityScripts/armored-chat/img/ui/social_black.png new file mode 100644 index 0000000000..16777af462 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/social_black.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/social_white.png b/scripts/communityScripts/armored-chat/img/ui/social_white.png new file mode 100644 index 0000000000..7677bd5469 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/social_white.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/world_black.png b/scripts/communityScripts/armored-chat/img/ui/world_black.png new file mode 100644 index 0000000000..c983e5df28 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/world_black.png differ diff --git a/scripts/communityScripts/armored-chat/img/ui/world_white.png b/scripts/communityScripts/armored-chat/img/ui/world_white.png new file mode 100644 index 0000000000..1f152b47b2 Binary files /dev/null and b/scripts/communityScripts/armored-chat/img/ui/world_white.png differ diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 1cbadadb67..a9bc2be591 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -7,7 +7,7 @@ // // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -47,7 +47,7 @@ var DEFAULT_SCRIPTS_SEPARATE = [ "communityScripts/notificationCore/notificationCore.js", "simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js", {"stable": "system/more/app-more.js", "beta": "https://more.overte.org/more/app-more.js"}, - "communityScripts/chat/FloofChat.js", + "communityScripts/armored-chat/armored_chat.js", //"system/chat.js" ]; diff --git a/scripts/developer/tests/raypickTester.js b/scripts/developer/tests/raypickTester.js index 83b2f3be72..ac70200b14 100644 --- a/scripts/developer/tests/raypickTester.js +++ b/scripts/developer/tests/raypickTester.js @@ -36,8 +36,8 @@ var pickID = Picks.createPick(PickType.Ray, { filter: PICK_FILTERS, enabled: true, }); -var blacklist = [ overlayID ]; // exclude hover text from ray pick results -Picks.setIgnoreItems(pickID, blacklist); +var blocklist = [ overlayID ]; // exclude hover text from ray pick results +Picks.setIgnoreItems(pickID, blocklist); Script.scriptEnding.connect(function() { Picks.removePick(pickID); }); diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index f2b0efcfa1..8f4e95fc32 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -56,7 +56,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.veryhighVarianceCount = 0; this.orderedPluginNames = []; this.tabletID = null; - this.blacklist = []; + this.blocklist = []; this.pointerManager = new PointerManager(); this.grabSphereOverlays = [null, null]; this.targetIDs = {}; @@ -169,8 +169,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.setIgnorePointerItems = function() { if (HMD.tabletID && HMD.tabletID !== this.tabletID) { this.tabletID = HMD.tabletID; - Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist); - Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist); + Pointers.setIgnoreItems(_this.leftPointer, _this.blocklist); + Pointers.setIgnoreItems(_this.rightPointer, _this.blocklist); } }; @@ -547,19 +547,19 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } }; - this.leftBlacklistTabletIDs = []; - this.rightBlacklistTabletIDs = []; + this.leftBlocklistTabletIDs = []; + this.rightBlocklistTabletIDs = []; - this.setLeftBlacklist = function () { - Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat(_this.leftBlacklistTabletIDs)); + this.setLeftBlocklist = function () { + Pointers.setIgnoreItems(_this.leftPointer, _this.blocklist.concat(_this.leftBlocklistTabletIDs)); }; - this.setRightBlacklist = function () { - Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat(_this.rightBlacklistTabletIDs)); + this.setRightBlocklist = function () { + Pointers.setIgnoreItems(_this.rightPointer, _this.blocklist.concat(_this.rightBlocklistTabletIDs)); }; - this.setBlacklist = function() { - _this.setLeftBlacklist(); - _this.setRightBlacklist(); + this.setBlocklist = function() { + _this.setLeftBlocklist(); + _this.setRightBlocklist(); }; var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; @@ -634,34 +634,34 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var message; if (sender === MyAvatar.sessionUUID) { try { - if (channel === 'Hifi-Hand-RayPick-Blacklist') { + if (channel === 'Hifi-Hand-RayPick-Blocklist') { message = JSON.parse(data); var action = message.action; var id = message.id; - var index = _this.blacklist.indexOf(id); + var index = _this.blocklist.indexOf(id); if (action === 'add' && index === -1) { - _this.blacklist.push(id); - _this.setBlacklist(); + _this.blocklist.push(id); + _this.setBlocklist(); } if (action === 'remove') { if (index > -1) { - _this.blacklist.splice(index, 1); - _this.setBlacklist(); + _this.blocklist.splice(index, 1); + _this.setBlocklist(); } } if (action === "tablet") { - var tabletIDs = message.blacklist ? + var tabletIDs = message.blocklist ? [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] : []; if (message.hand === LEFT_HAND) { - _this.leftBlacklistTabletIDs = tabletIDs; - _this.setLeftBlacklist(); + _this.leftBlocklistTabletIDs = tabletIDs; + _this.setLeftBlocklist(); } else { - _this.rightBlacklistTabletIDs = tabletIDs; - _this.setRightBlacklist(); + _this.rightBlocklistTabletIDs = tabletIDs; + _this.setRightBlocklist(); } } } @@ -737,7 +737,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Entities.mousePressOnEntity.connect(mousePress); var controllerDispatcher = new ControllerDispatcher(); - Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); + Messages.subscribe('Hifi-Hand-RayPick-Blocklist'); Messages.messageReceived.connect(controllerDispatcher.handleMessage); Picks.handLaserDelayChanged.connect(controllerDispatcher.handLaserDelayChanged); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 4c61e22764..4fabcae04d 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -299,7 +299,7 @@ Script.include("/~/system/libraries/controllers.js"); action: 'remove', id: this.ignoredEntities[i] }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); + Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data)); } this.ignoredEntities = []; }; @@ -394,7 +394,7 @@ Script.include("/~/system/libraries/controllers.js"); action: 'add', id: intersection.objectID }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); + Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data)); this.ignoredEntities.push(intersection.objectID); } } diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 22ce55c703..078f159d20 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -229,7 +229,7 @@ Script.include("/~/system/libraries/utils.js"); enableDispatcherModule("RightHandInEditMode", rightHandInEditMode); var INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status"; - var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; + var HAND_RAYPICK_BLOCKLIST_CHANNEL = "Hifi-Hand-RayPick-Blocklist"; this.handleMessage = function (channel, data, sender) { if (channel === INEDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { var message; @@ -247,10 +247,10 @@ Script.include("/~/system/libraries/utils.js"); } else { rightHandInEditMode.isEditing = message.editing; } - Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ + Messages.sendLocalMessage(HAND_RAYPICK_BLOCKLIST_CHANNEL, JSON.stringify({ action: "tablet", hand: message.hand, - blacklist: message.editing + blocklist: message.editing })); break; } diff --git a/scripts/system/controllers/controllerModules/inVREditMode.js b/scripts/system/controllers/controllerModules/inVREditMode.js index 1483a19feb..edd995d96b 100644 --- a/scripts/system/controllers/controllerModules/inVREditMode.js +++ b/scripts/system/controllers/controllerModules/inVREditMode.js @@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); enableDispatcherModule("RightHandInVREditMode", rightHandInVREditMode); var INVREDIT_STATUS_CHANNEL = "Hifi-InVREdit-Status"; - var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; + var HAND_RAYPICK_BLOCKLIST_CHANNEL = "Hifi-Hand-RayPick-Blocklist"; this.handleMessage = function (channel, data, sender) { if (channel === INVREDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { var message; @@ -168,10 +168,10 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } else { rightHandInVREditMode.isEditing = message.editing; } - Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ + Messages.sendLocalMessage(HAND_RAYPICK_BLOCKLIST_CHANNEL, JSON.stringify({ action: "tablet", hand: message.hand, - blacklist: message.editing + blocklist: message.editing })); break; } diff --git a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js index e5cccaf047..8494bc0db1 100644 --- a/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js +++ b/scripts/system/controllers/controllerModules/webSurfaceLaserInput.js @@ -113,7 +113,7 @@ Script.include("/~/system/libraries/controllers.js"); action: 'add', id: objectID }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); + Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data)); this.ignoredObjects.push(objectID); } } else if (intersection.type === Picks.INTERSECTED_ENTITY) { @@ -122,7 +122,7 @@ Script.include("/~/system/libraries/controllers.js"); action: 'add', id: objectID }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); + Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data)); this.ignoredObjects.push(objectID); } } @@ -134,7 +134,7 @@ Script.include("/~/system/libraries/controllers.js"); action: 'remove', id: this.ignoredObjects[index] }; - Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data)); + Messages.sendMessage('Hifi-Hand-RayPick-Blocklist', JSON.stringify(data)); } this.ignoredObjects = []; diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 2901f7c024..6d0cd6f96e 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -58,7 +58,7 @@ function runDefaultsTogether() { function runDefaultsSeparately() { for (var i in CONTOLLER_SCRIPTS) { if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) { - print("loading " + CONTOLLER_SCRIPTS[j]); + print("loading " + CONTOLLER_SCRIPTS[i]); Script.load(CONTOLLER_SCRIPTS[i]); } } diff --git a/scripts/system/controllers/mouseLook.js b/scripts/system/controllers/mouseLook.js index 751bda2150..c8e822646d 100644 --- a/scripts/system/controllers/mouseLook.js +++ b/scripts/system/controllers/mouseLook.js @@ -1,204 +1,98 @@ -/* -mouseLook.js – mouse look switching script -by rampa3 (https://github.com/rampa3) and vegaslon (https://github.com/vegaslon) -*/ -(function() { // BEGIN LOCAL_SCOPE +// +// mouseLook.js +// +// By Armored Dragon (June 6). Refactored from Rampa3 & Vegaslon work +// Copyright 2024 Overte e.V. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// - var away; +(() => { + // States ---- + let mouseLookActive = Settings.getValue("mouselook-active", false); + let mouseLookEnabled = Camera.getMouseLook(); + let hmdActive = HMD.active; + let overlayActive = Desktop.isOverlayWindowFocused(); - var hmd = HMD.active; - - var mouseLookEnabled = Camera.getMouseLook(); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - var tabletUp; - - var keysOnOverlay = Desktop.isOverlayWindowFocused(); - - var tempOff = false; - - var altMode = false; + // Resources ---- + let tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + // Events ---- Camera.mouseLookChanged.connect(onMouseLookChanged); + Controller.keyPressEvent.connect(onKeyPressEvent); + Desktop.uiFocusChanged.connect(onUiFocusChanged); + HMD.displayModeChanged.connect(onDisplayModeChanged); + MyAvatar.wentActive.connect(onWentActive); + MyAvatar.wentAway.connect(onWentAway); + tablet.tabletShownChanged.connect(onTabletShownChanged); + Script.scriptEnding.connect(onScriptEnding); + // Program ---- function onMouseLookChanged(newMouseLook) { + disableMouseLook(); mouseLookEnabled = newMouseLook; } - if (!hmd){ - if (mouseLookEnabled) { - if (!keysOnOverlay) { - if (!tablet.tabletShown){ - Window.displayAnnouncement("Mouse look: ON"); - mouseLookOn(); - } else { - Window.displayAnnouncement("Tablet is up – mouse look temporarily OFF."); - } - } - } - } - - Controller.keyPressEvent.connect(onKeyPressEvent); - function onKeyPressEvent(event) { - if (!hmd){ - if(event.isAlt){ - if (keysOnOverlay) return; - if (!mouseLookEnabled) return; - mouseLookOff(); - Window.displayAnnouncement("Mouse look: Temporarily OFF"); - tempOff = true; - altMode = true; - } - if (tempOff && altMode && ['left', 'right', 'up', 'down', 'esc', 'w', 'a', 's', 'd'].includes(event.text.toLowerCase())){ - if (keysOnOverlay) return; - if (!mouseLookEnabled) return; - mouseLookOn(); - tempOff = false; - altMode = false - } - if (event.text.toLowerCase() === 'm') { - if (!keysOnOverlay) { - if (mouseLookEnabled) { - if (!Camera.getCaptureMouse()){ - tempOff = false; - Window.displayAnnouncement("Mouse look: ON"); - mouseLookOn(); - } else { - tempOff = true; - Window.displayAnnouncement("Mouse look: Temporarily OFF"); - mouseLookOff(); - } - } - } + // Toggle using the m key + if (event.text.toLowerCase() === "m") { + if (Camera.captureMouse) { + disableMouseLook(); + } else { + mouseLookActive = true; + Settings.setValue("mouselook-active", true); + enableMouseLook(); } } } - tablet.tabletShownChanged.connect(onTabletShownChanged); - function onTabletShownChanged() { - if (!hmd) { - if (mouseLookEnabled) { - if (!tablet.toolbarMode) { - if (!keysOnOverlay) { - if (tablet.tabletShown) { - tabletUp = true; - if (!tempOff) { - if (!away) { - Window.displayAnnouncement("Tablet is up – mouse look temporarily OFF."); - mouseLookOff(); - } - } - } else if (!tablet.tabletShown) { - tabletUp = false; - if (!tempOff) { - if (!away && !keysOnOverlay) { - Window.displayAnnouncement("Tablet hidden – mouse look ON."); - mouseLookOn(); - } - } - } - } - } - } - } + if (tablet.tabletShown) disableMouseLook(); + else enableMouseLook(); } - MyAvatar.wentAway.connect(onWentAway); - function onWentAway() { - if (!hmd) { - if (mouseLookEnabled) { - away = true; - if (!keysOnOverlay) { - if (!tabletUp){ - Window.displayAnnouncement("Away state ON – mouse look temporarily OFF.") - tempOff = false; - mouseLookOff() - } - } - } - } + disableMouseLook(); } - MyAvatar.wentActive.connect(onWentActive); - function onWentActive() { - if (!hmd) { - if (mouseLookEnabled) { - away = false; - if (!keysOnOverlay) { - if (!tabletUp) { - Window.displayAnnouncement("Away state OFF – mouse look ON."); - mouseLookOn(); - } - } - } - } + enableMouseLook(); } - HMD.displayModeChanged.connect(onDisplayModeChanged); - function onDisplayModeChanged() { - if (mouseLookEnabled) { - if (HMD.active) { - hmd = true; - mouseLookOff(); - } else { - hmd = false; - if (!tempOff) { - if (!keysOnOverlay) { - if (!tabletUp) { - mouseLookOn(); - } - } - } - } + hmdActive = HMD.active; + if (hmdActive) disableMouseLook(); + else enableMouseLook(); + } + + function onUiFocusChanged(keyFocus) { + if (keyFocus) { + overlayActive = true; + disableMouseLook(); + } else { + overlayActive = false; + enableMouseLook(); } } - function mouseLookOn() { - if (mouseLookEnabled) - Camera.captureMouse = true; + function enableMouseLook() { + if (hmdActive) return; + if (tablet.tabletShown) return; + if (overlayActive) return; + if (!mouseLookEnabled) return; // Mouse look disabled via setting + if (!mouseLookActive) return; // Mouse look disabled via the hotkey + + Camera.captureMouse = true; } - function mouseLookOff() { + function disableMouseLook() { + mouseLookActive = false; + Settings.setValue("mouselook-active", false); + Camera.captureMouse = false; } - - Desktop.uiFocusChanged.connect(onUiFocusChanged); - - function onUiFocusChanged(keyFocus) { - if (!hmd) { - if (mouseLookEnabled) { - if (keyFocus) { - keysOnOverlay = true; - if (Camera.captureMouse) { - mouseLookOff(); - } - } else { - keysOnOverlay = false; - if (!tablet.tabletShown) { - if (!tempOff) { - if (!away) { - mouseLookOn(); - } - } - } - } - } - } - } - - Messages.messageReceived.connect(onMessageReceived); - function onMessageReceived(channel, message, sender, localOnly) { - if (channel === "Hifi-Away-Enable") - if (message === 'enable') mouseLookOn(); - } - - Script.scriptEnding.connect(onScriptEnding); function onScriptEnding() { Camera.captureMouse = false; @@ -211,5 +105,4 @@ by rampa3 (https://github.com/rampa3) and vegaslon (https://github.com/vegaslon) Desktop.uiFocusChanged.disconnect(onUiFocusChanged); Script.scriptEnding.disconnect(onScriptEnding); } - -}()); // END LOCAL_SCOPE +})(); diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index a85e3b00ef..5fd7892fae 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -5,7 +5,7 @@ // Created by Ryan Huffman on 13 Nov 2014 // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2022-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -63,131 +63,298 @@